@lenne.tech/cli 0.0.123 → 0.0.124
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.
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const fs = require("fs");
|
|
13
|
+
const path = require("path");
|
|
14
|
+
const util_1 = require("util");
|
|
15
|
+
const execAsync = (0, util_1.promisify)(require('child_process').exec);
|
|
16
|
+
/**
|
|
17
|
+
* Export MongoDB collection to JSON file
|
|
18
|
+
*/
|
|
19
|
+
const command = {
|
|
20
|
+
alias: ['ce'],
|
|
21
|
+
description: 'Export MongoDB collection to JSON file',
|
|
22
|
+
name: 'collection-export',
|
|
23
|
+
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
const { helper, parameters, print: { error, info, spin, success, warning }, prompt, system, } = toolbox;
|
|
25
|
+
// Start timer
|
|
26
|
+
const timer = system.startTimer();
|
|
27
|
+
info('MongoDB Collection Export');
|
|
28
|
+
info('');
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Step 1: MongoDB Connection
|
|
31
|
+
// ============================================================================
|
|
32
|
+
info('Step 1: MongoDB Connection');
|
|
33
|
+
info('');
|
|
34
|
+
const mongoUri = yield helper.getInput(parameters.options.mongoUri || process.env.MONGO_URI || 'mongodb://127.0.0.1:27017', {
|
|
35
|
+
initial: 'mongodb://127.0.0.1:27017',
|
|
36
|
+
name: 'MongoDB Connection URI',
|
|
37
|
+
showError: true,
|
|
38
|
+
});
|
|
39
|
+
if (!mongoUri) {
|
|
40
|
+
error('MongoDB URI is required');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Step 2: List Databases
|
|
45
|
+
// ============================================================================
|
|
46
|
+
info('');
|
|
47
|
+
info('Step 2: Fetching databases...');
|
|
48
|
+
info('');
|
|
49
|
+
let databases = [];
|
|
50
|
+
const systemDatabases = ['admin', 'local', 'config'];
|
|
51
|
+
try {
|
|
52
|
+
const listDbSpin = spin('Listing databases');
|
|
53
|
+
// Use mongo shell to list databases
|
|
54
|
+
const listDbCommand = `mongosh "${mongoUri}" --quiet --eval "JSON.stringify(db.adminCommand('listDatabases').databases.map(d => d.name))"`;
|
|
55
|
+
const { stdout } = yield execAsync(listDbCommand);
|
|
56
|
+
const allDatabases = JSON.parse(stdout.trim());
|
|
57
|
+
// Filter out system databases
|
|
58
|
+
databases = allDatabases.filter((db) => !systemDatabases.includes(db));
|
|
59
|
+
if (databases.length === 0) {
|
|
60
|
+
listDbSpin.fail('No user databases found');
|
|
61
|
+
warning('Only system databases (admin, local, config) are available');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
listDbSpin.succeed(`Found ${databases.length} database(s)`);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
error(`Failed to list databases: ${err.message}`);
|
|
68
|
+
info('');
|
|
69
|
+
info('Please ensure:');
|
|
70
|
+
info('- MongoDB is running and accessible');
|
|
71
|
+
info('- mongosh (MongoDB Shell) is installed');
|
|
72
|
+
info('- The MongoDB URI is correct');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Step 3: Select Database
|
|
77
|
+
// ============================================================================
|
|
78
|
+
info('');
|
|
79
|
+
info('Step 3: Select database');
|
|
80
|
+
info('');
|
|
81
|
+
let selectedDatabase;
|
|
82
|
+
if (parameters.options.database) {
|
|
83
|
+
selectedDatabase = parameters.options.database;
|
|
84
|
+
if (!databases.includes(selectedDatabase)) {
|
|
85
|
+
error(`Database "${selectedDatabase}" not found`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
success(`Using database: ${selectedDatabase}`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const { database } = yield prompt.ask({
|
|
92
|
+
choices: databases,
|
|
93
|
+
initial: 0,
|
|
94
|
+
message: 'Select database:',
|
|
95
|
+
name: 'database',
|
|
96
|
+
type: 'select',
|
|
97
|
+
});
|
|
98
|
+
if (!database) {
|
|
99
|
+
error('No database selected');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
selectedDatabase = database;
|
|
103
|
+
success(`Selected database: ${selectedDatabase}`);
|
|
104
|
+
}
|
|
105
|
+
// ============================================================================
|
|
106
|
+
// Step 4: List Collections
|
|
107
|
+
// ============================================================================
|
|
108
|
+
info('');
|
|
109
|
+
info('Step 4: Fetching collections...');
|
|
110
|
+
info('');
|
|
111
|
+
let collections = [];
|
|
112
|
+
try {
|
|
113
|
+
const listCollSpin = spin('Listing collections');
|
|
114
|
+
// Use mongo shell to list collections
|
|
115
|
+
const listCollCommand = `mongosh "${mongoUri}/${selectedDatabase}" --quiet --eval "JSON.stringify(db.getCollectionNames())"`;
|
|
116
|
+
const { stdout } = yield execAsync(listCollCommand);
|
|
117
|
+
collections = JSON.parse(stdout.trim());
|
|
118
|
+
if (collections.length === 0) {
|
|
119
|
+
listCollSpin.fail('No collections found in this database');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
listCollSpin.succeed(`Found ${collections.length} collection(s)`);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
error(`Failed to list collections: ${err.message}`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// Step 5: Select Collection
|
|
130
|
+
// ============================================================================
|
|
131
|
+
info('');
|
|
132
|
+
info('Step 5: Select collection');
|
|
133
|
+
info('');
|
|
134
|
+
let selectedCollection;
|
|
135
|
+
if (parameters.options.collection) {
|
|
136
|
+
selectedCollection = parameters.options.collection;
|
|
137
|
+
if (!collections.includes(selectedCollection)) {
|
|
138
|
+
error(`Collection "${selectedCollection}" not found`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
success(`Using collection: ${selectedCollection}`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
const { collection } = yield prompt.ask({
|
|
145
|
+
choices: collections,
|
|
146
|
+
initial: 0,
|
|
147
|
+
message: 'Select collection:',
|
|
148
|
+
name: 'collection',
|
|
149
|
+
type: 'select',
|
|
150
|
+
});
|
|
151
|
+
if (!collection) {
|
|
152
|
+
error('No collection selected');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
selectedCollection = collection;
|
|
156
|
+
success(`Selected collection: ${selectedCollection}`);
|
|
157
|
+
}
|
|
158
|
+
// Get document count
|
|
159
|
+
try {
|
|
160
|
+
const countCommand = `mongosh "${mongoUri}/${selectedDatabase}" --quiet --eval "db.${selectedCollection}.countDocuments()"`;
|
|
161
|
+
const { stdout } = yield execAsync(countCommand);
|
|
162
|
+
const count = parseInt(stdout.trim(), 10);
|
|
163
|
+
info(`Collection contains ${count} document(s)`);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
warning(`Could not get document count: ${err.message}`);
|
|
167
|
+
}
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// Step 6: Output File Path
|
|
170
|
+
// ============================================================================
|
|
171
|
+
info('');
|
|
172
|
+
info('Step 6: Output file path');
|
|
173
|
+
info('');
|
|
174
|
+
const defaultFilename = `${selectedDatabase}_${selectedCollection}_${Date.now()}.json`;
|
|
175
|
+
const defaultPath = path.join(process.cwd(), defaultFilename);
|
|
176
|
+
const outputPath = yield helper.getInput(parameters.options.output || defaultPath, {
|
|
177
|
+
initial: defaultPath,
|
|
178
|
+
name: 'Output file path',
|
|
179
|
+
showError: true,
|
|
180
|
+
});
|
|
181
|
+
if (!outputPath) {
|
|
182
|
+
error('Output path is required');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Check if file exists
|
|
186
|
+
if (yield toolbox.filesystem.existsAsync(outputPath)) {
|
|
187
|
+
const { overwrite } = yield prompt.ask({
|
|
188
|
+
initial: false,
|
|
189
|
+
message: `File "${outputPath}" already exists. Overwrite?`,
|
|
190
|
+
name: 'overwrite',
|
|
191
|
+
type: 'confirm',
|
|
192
|
+
});
|
|
193
|
+
if (!overwrite) {
|
|
194
|
+
info('Export cancelled');
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Ensure directory exists
|
|
199
|
+
const outputDir = path.dirname(outputPath);
|
|
200
|
+
try {
|
|
201
|
+
yield fs.promises.mkdir(outputDir, { recursive: true });
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
error(`Failed to create directory: ${err.message}`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// ============================================================================
|
|
208
|
+
// Step 7: Export Data
|
|
209
|
+
// ============================================================================
|
|
210
|
+
info('');
|
|
211
|
+
info('Step 7: Exporting data...');
|
|
212
|
+
info('');
|
|
213
|
+
try {
|
|
214
|
+
const exportSpin = spin(`Exporting ${selectedDatabase}.${selectedCollection}`);
|
|
215
|
+
// Use mongoexport to export collection
|
|
216
|
+
const exportCommand = `mongoexport --uri="${mongoUri}/${selectedDatabase}" --collection="${selectedCollection}" --out="${outputPath}" --jsonArray`;
|
|
217
|
+
const { stderr } = yield execAsync(exportCommand, {
|
|
218
|
+
maxBuffer: 1024 * 1024 * 100, // 100MB buffer
|
|
219
|
+
});
|
|
220
|
+
// mongoexport outputs progress to stderr, check for actual errors
|
|
221
|
+
if (stderr && stderr.toLowerCase().includes('error') && !stderr.includes('exported')) {
|
|
222
|
+
throw new Error(stderr);
|
|
223
|
+
}
|
|
224
|
+
exportSpin.succeed('Data exported successfully');
|
|
225
|
+
// Get file size
|
|
226
|
+
const stats = yield fs.promises.stat(outputPath);
|
|
227
|
+
const fileSizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
228
|
+
info(`File size: ${fileSizeMB} MB`);
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
error(`Failed to export data: ${err.message}`);
|
|
232
|
+
info('');
|
|
233
|
+
info('Please ensure:');
|
|
234
|
+
info('- MongoDB is running and accessible');
|
|
235
|
+
info('- mongoexport tool is installed (part of MongoDB Database Tools)');
|
|
236
|
+
info('- You have read permissions on the database/collection');
|
|
237
|
+
info('- You have write permissions to the output directory');
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// ============================================================================
|
|
241
|
+
// Done
|
|
242
|
+
// ============================================================================
|
|
243
|
+
info('');
|
|
244
|
+
success(`Collection exported successfully in ${helper.msToMinutesAndSeconds(timer())}m`);
|
|
245
|
+
success(`Output: ${outputPath}`);
|
|
246
|
+
info('');
|
|
247
|
+
if (!parameters.options.fromGluegunMenu) {
|
|
248
|
+
process.exit(0);
|
|
249
|
+
}
|
|
250
|
+
return `mongodb export ${selectedDatabase}.${selectedCollection}`;
|
|
251
|
+
}),
|
|
252
|
+
};
|
|
253
|
+
exports.default = command;
|
|
254
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi1leHBvcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tbWFuZHMvbW9uZ29kYi9jb2xsZWN0aW9uLWV4cG9ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBLHlCQUF5QjtBQUV6Qiw2QkFBNkI7QUFDN0IsK0JBQWlDO0FBSWpDLE1BQU0sU0FBUyxHQUFHLElBQUEsZ0JBQVMsRUFBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7QUFFM0Q7O0dBRUc7QUFDSCxNQUFNLE9BQU8sR0FBbUI7SUFDOUIsS0FBSyxFQUFFLENBQUMsSUFBSSxDQUFDO0lBQ2IsV0FBVyxFQUFFLHdDQUF3QztJQUNyRCxJQUFJLEVBQUUsbUJBQW1CO0lBQ3pCLEdBQUcsRUFBRSxDQUFPLE9BQStCLEVBQUUsRUFBRTtRQUM3QyxNQUFNLEVBQ0osTUFBTSxFQUNOLFVBQVUsRUFDVixLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQzlDLE1BQU0sRUFDTixNQUFNLEdBQ1AsR0FBRyxPQUFPLENBQUM7UUFFWixjQUFjO1FBQ2QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBRWxDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVULCtFQUErRTtRQUMvRSw2QkFBNkI7UUFDN0IsK0VBQStFO1FBRS9FLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO1FBQ25DLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVULE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLFFBQVEsQ0FDcEMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksMkJBQTJCLEVBQ25G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
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
/**
|
|
13
|
+
* MongoDB commands
|
|
14
|
+
*/
|
|
15
|
+
const command = {
|
|
16
|
+
alias: ['mdb'],
|
|
17
|
+
description: 'MongoDB operations (export, restore, etc.)',
|
|
18
|
+
hidden: false,
|
|
19
|
+
name: 'mongodb',
|
|
20
|
+
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
yield toolbox.helper.showMenu('mongodb', {
|
|
22
|
+
headline: 'MongoDB Commands',
|
|
23
|
+
});
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
exports.default = command;
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uZ29kYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9tb25nb2RiL21vbmdvZGIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFFQTs7R0FFRztBQUNILE1BQU0sT0FBTyxHQUFHO0lBQ2QsS0FBSyxFQUFFLENBQUMsS0FBSyxDQUFDO0lBQ2QsV0FBVyxFQUFFLDRDQUE0QztJQUN6RCxNQUFNLEVBQUUsS0FBSztJQUNiLElBQUksRUFBRSxTQUFTO0lBQ2YsR0FBRyxFQUFFLENBQU8sT0FBK0IsRUFBRSxFQUFFO1FBQzdDLE1BQU0sT0FBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFO1lBQ3ZDLFFBQVEsRUFBRSxrQkFBa0I7U0FDN0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFBO0NBQ0YsQ0FBQztBQUVGLGtCQUFlLE9BQU8sQ0FBQyJ9
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
20
|
+
const fs = require("fs");
|
|
21
|
+
const path = require("path");
|
|
22
|
+
const util_1 = require("util");
|
|
23
|
+
const execAsync = (0, util_1.promisify)(require('child_process').exec);
|
|
24
|
+
/**
|
|
25
|
+
* Restore MongoDB database from S3 backup
|
|
26
|
+
*/
|
|
27
|
+
const command = {
|
|
28
|
+
alias: ['s3r'],
|
|
29
|
+
description: 'Restore MongoDB database from S3 backup',
|
|
30
|
+
name: 's3-restore',
|
|
31
|
+
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
+
var _a, e_1, _b, _c;
|
|
33
|
+
const { helper, parameters, print: { error, info, spin, success, warning }, prompt, system, } = toolbox;
|
|
34
|
+
// Start timer
|
|
35
|
+
const timer = system.startTimer();
|
|
36
|
+
info('MongoDB Restore from S3');
|
|
37
|
+
info('');
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Step 1: S3 Configuration
|
|
40
|
+
// ============================================================================
|
|
41
|
+
info('Step 1: S3 Configuration');
|
|
42
|
+
info('');
|
|
43
|
+
const s3Bucket = yield helper.getInput(parameters.options.bucket || process.env.S3_BUCKET, {
|
|
44
|
+
name: 'S3 Bucket Name',
|
|
45
|
+
showError: true,
|
|
46
|
+
});
|
|
47
|
+
if (!s3Bucket) {
|
|
48
|
+
error('S3 Bucket is required');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const s3Key = yield helper.getInput(parameters.options.key || process.env.S3_KEY, {
|
|
52
|
+
name: 'S3 Access Key ID',
|
|
53
|
+
showError: true,
|
|
54
|
+
});
|
|
55
|
+
if (!s3Key) {
|
|
56
|
+
error('S3 Access Key ID is required');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const s3Secret = yield helper.getInput(parameters.options.secret || process.env.S3_SECRET, {
|
|
60
|
+
name: 'S3 Secret Access Key',
|
|
61
|
+
showError: true,
|
|
62
|
+
});
|
|
63
|
+
if (!s3Secret) {
|
|
64
|
+
error('S3 Secret Access Key is required');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const s3Url = yield helper.getInput(parameters.options.url || process.env.S3_URL, {
|
|
68
|
+
name: 'S3 Endpoint URL',
|
|
69
|
+
showError: true,
|
|
70
|
+
});
|
|
71
|
+
if (!s3Url) {
|
|
72
|
+
error('S3 Endpoint URL is required');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const s3Region = yield helper.getInput(parameters.options.region || process.env.S3_REGION || 'de', {
|
|
76
|
+
initial: 'de',
|
|
77
|
+
name: 'S3 Region (optional)',
|
|
78
|
+
showError: false,
|
|
79
|
+
});
|
|
80
|
+
const s3Folder = yield helper.getInput(parameters.options.folder || process.env.S3_FOLDER || '', {
|
|
81
|
+
initial: '',
|
|
82
|
+
name: 'S3 Folder/Prefix (optional)',
|
|
83
|
+
showError: false,
|
|
84
|
+
});
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// Step 2: Initialize S3 Client and List Backups
|
|
87
|
+
// ============================================================================
|
|
88
|
+
info('');
|
|
89
|
+
info('Step 2: Fetching available backups from S3...');
|
|
90
|
+
info('');
|
|
91
|
+
let s3Client;
|
|
92
|
+
let backupFiles = [];
|
|
93
|
+
try {
|
|
94
|
+
s3Client = new client_s3_1.S3({
|
|
95
|
+
credentials: {
|
|
96
|
+
accessKeyId: s3Key,
|
|
97
|
+
secretAccessKey: s3Secret,
|
|
98
|
+
},
|
|
99
|
+
endpoint: s3Url,
|
|
100
|
+
forcePathStyle: true,
|
|
101
|
+
region: s3Region,
|
|
102
|
+
});
|
|
103
|
+
const listSpin = spin('Listing backup files from S3');
|
|
104
|
+
// List all backup files from S3
|
|
105
|
+
const paginator = (0, client_s3_1.paginateListObjectsV2)({ client: s3Client }, {
|
|
106
|
+
Bucket: s3Bucket,
|
|
107
|
+
Prefix: s3Folder,
|
|
108
|
+
});
|
|
109
|
+
try {
|
|
110
|
+
for (var _d = true, paginator_1 = __asyncValues(paginator), paginator_1_1; paginator_1_1 = yield paginator_1.next(), _a = paginator_1_1.done, !_a; _d = true) {
|
|
111
|
+
_c = paginator_1_1.value;
|
|
112
|
+
_d = false;
|
|
113
|
+
const page = _c;
|
|
114
|
+
const objects = page.Contents;
|
|
115
|
+
if (!(objects === null || objects === void 0 ? void 0 : objects.length)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
backupFiles = [
|
|
119
|
+
...backupFiles,
|
|
120
|
+
...objects
|
|
121
|
+
.filter(object => object.Key && (object.Key.endsWith('.tar.gz') || object.Key.endsWith('.archive')))
|
|
122
|
+
.map(object => ({
|
|
123
|
+
key: object.Key,
|
|
124
|
+
label: object.Key.split('/').pop() || object.Key,
|
|
125
|
+
lastModified: object.LastModified,
|
|
126
|
+
size: object.Size,
|
|
127
|
+
})),
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
132
|
+
finally {
|
|
133
|
+
try {
|
|
134
|
+
if (!_d && !_a && (_b = paginator_1.return)) yield _b.call(paginator_1);
|
|
135
|
+
}
|
|
136
|
+
finally { if (e_1) throw e_1.error; }
|
|
137
|
+
}
|
|
138
|
+
// Sort by last modified date (newest first)
|
|
139
|
+
backupFiles.sort((a, b) => {
|
|
140
|
+
if (!a.lastModified || !b.lastModified) {
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
return b.lastModified.getTime() - a.lastModified.getTime();
|
|
144
|
+
});
|
|
145
|
+
listSpin.succeed(`Found ${backupFiles.length} backup file(s)`);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
error(`Failed to connect to S3 or list backups: ${err.message}`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (backupFiles.length === 0) {
|
|
152
|
+
warning('No backup files found in the specified S3 bucket/folder');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Step 3: Select Backup File
|
|
157
|
+
// ============================================================================
|
|
158
|
+
info('');
|
|
159
|
+
info('Step 3: Select backup file');
|
|
160
|
+
info('');
|
|
161
|
+
// Format backup files for selection with additional info
|
|
162
|
+
const backupChoices = backupFiles.map((file, index) => {
|
|
163
|
+
const sizeStr = file.size ? `${(file.size / 1024 / 1024).toFixed(2)} MB` : 'Unknown size';
|
|
164
|
+
const dateStr = file.lastModified
|
|
165
|
+
? file.lastModified.toLocaleString('de-DE', {
|
|
166
|
+
day: '2-digit',
|
|
167
|
+
hour: '2-digit',
|
|
168
|
+
minute: '2-digit',
|
|
169
|
+
month: '2-digit',
|
|
170
|
+
year: 'numeric',
|
|
171
|
+
})
|
|
172
|
+
: 'Unknown date';
|
|
173
|
+
const marker = index === 0 ? ' (newest)' : '';
|
|
174
|
+
return {
|
|
175
|
+
message: `${file.label}${marker} - ${dateStr} - ${sizeStr}`,
|
|
176
|
+
name: file.key,
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
const { selectedBackupKey } = yield prompt.ask({
|
|
180
|
+
choices: backupChoices,
|
|
181
|
+
initial: 0, // Pre-select the newest (first) backup
|
|
182
|
+
message: 'Select backup file to restore:',
|
|
183
|
+
name: 'selectedBackupKey',
|
|
184
|
+
type: 'select',
|
|
185
|
+
});
|
|
186
|
+
if (!selectedBackupKey) {
|
|
187
|
+
error('No backup file selected');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const selectedBackup = backupFiles.find(f => f.key === selectedBackupKey);
|
|
191
|
+
if (!selectedBackup) {
|
|
192
|
+
error('Selected backup not found');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
success(`Selected: ${selectedBackup.label}`);
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// Step 4: Download Backup
|
|
198
|
+
// ============================================================================
|
|
199
|
+
info('');
|
|
200
|
+
info('Step 4: Downloading backup...');
|
|
201
|
+
info('');
|
|
202
|
+
const tempDir = path.join('/tmp', `backup-${Date.now()}`);
|
|
203
|
+
const backupFile = path.join(tempDir, 'backup.archive');
|
|
204
|
+
try {
|
|
205
|
+
yield fs.promises.mkdir(tempDir, { recursive: true });
|
|
206
|
+
const downloadSpin = spin(`Downloading ${selectedBackup.label}`);
|
|
207
|
+
const command = {
|
|
208
|
+
Bucket: s3Bucket,
|
|
209
|
+
Key: selectedBackup.key,
|
|
210
|
+
};
|
|
211
|
+
const data = yield s3Client.getObject(command);
|
|
212
|
+
const bodyStream = data.Body;
|
|
213
|
+
const bodyArray = yield bodyStream.transformToByteArray();
|
|
214
|
+
yield fs.promises.writeFile(backupFile, Buffer.from(bodyArray));
|
|
215
|
+
downloadSpin.succeed(`Downloaded ${selectedBackup.label} (${(bodyArray.length / 1024 / 1024).toFixed(2)} MB)`);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
error(`Failed to download backup: ${err.message}`);
|
|
219
|
+
// Cleanup
|
|
220
|
+
try {
|
|
221
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
222
|
+
}
|
|
223
|
+
catch (e) {
|
|
224
|
+
// Ignore cleanup errors
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// ============================================================================
|
|
229
|
+
// Step 5: Extract Backup
|
|
230
|
+
// ============================================================================
|
|
231
|
+
info('');
|
|
232
|
+
info('Step 5: Extracting backup...');
|
|
233
|
+
info('');
|
|
234
|
+
const extractDir = path.join(tempDir, 'extracted');
|
|
235
|
+
try {
|
|
236
|
+
yield fs.promises.mkdir(extractDir, { recursive: true });
|
|
237
|
+
const extractSpin = spin('Extracting backup archive');
|
|
238
|
+
const extractCommand = `tar -xzf "${backupFile}" -C "${extractDir}"`;
|
|
239
|
+
yield execAsync(extractCommand);
|
|
240
|
+
extractSpin.succeed('Backup extracted');
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
error(`Failed to extract backup: ${err.message}`);
|
|
244
|
+
// Cleanup
|
|
245
|
+
try {
|
|
246
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
// Ignore cleanup errors
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
// ============================================================================
|
|
254
|
+
// Step 6: Find Databases in Backup
|
|
255
|
+
// ============================================================================
|
|
256
|
+
info('');
|
|
257
|
+
info('Step 6: Detecting databases from backup...');
|
|
258
|
+
info('');
|
|
259
|
+
let backupRootDir = '';
|
|
260
|
+
let sourceDbName = '';
|
|
261
|
+
const systemDatabases = ['admin', 'local', 'config'];
|
|
262
|
+
try {
|
|
263
|
+
const findDbSpin = spin('Searching for database files');
|
|
264
|
+
// Find all directories containing BSON files
|
|
265
|
+
const findBsonCommand = `find "${extractDir}" -name "*.bson" -exec dirname {} \\; | sort -u`;
|
|
266
|
+
const { stdout } = yield execAsync(findBsonCommand);
|
|
267
|
+
const dbPaths = stdout.trim().split('\n').filter(p => p);
|
|
268
|
+
if (dbPaths.length === 0) {
|
|
269
|
+
throw new Error('No database files found in backup');
|
|
270
|
+
}
|
|
271
|
+
// Find the common parent directory (backup root)
|
|
272
|
+
// Example: /tmp/backup-xxx/extracted/tmp/backup-name/admin -> parent is /tmp/backup-xxx/extracted/tmp/backup-name
|
|
273
|
+
const firstPath = dbPaths[0];
|
|
274
|
+
const pathParts = firstPath.split('/');
|
|
275
|
+
// The parent is everything except the last part (database name)
|
|
276
|
+
backupRootDir = pathParts.slice(0, -1).join('/');
|
|
277
|
+
// Get all database names from their directories
|
|
278
|
+
const dbNames = dbPaths
|
|
279
|
+
.map((p) => {
|
|
280
|
+
const parts = p.split('/');
|
|
281
|
+
return parts[parts.length - 1];
|
|
282
|
+
})
|
|
283
|
+
.filter((name, index, self) => self.indexOf(name) === index); // unique
|
|
284
|
+
// Filter out system databases
|
|
285
|
+
const userDatabases = dbNames.filter(name => !systemDatabases.includes(name));
|
|
286
|
+
if (userDatabases.length === 0) {
|
|
287
|
+
warning('Only system databases (admin, local, config) found in backup');
|
|
288
|
+
warning('Will proceed, but you may want to check the backup file');
|
|
289
|
+
sourceDbName = dbNames[0]; // Use first available database
|
|
290
|
+
}
|
|
291
|
+
else if (userDatabases.length === 1) {
|
|
292
|
+
sourceDbName = userDatabases[0];
|
|
293
|
+
findDbSpin.succeed(`Found database: ${sourceDbName}`);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
findDbSpin.succeed(`Found ${userDatabases.length} databases`);
|
|
297
|
+
// Let user select which database to restore
|
|
298
|
+
info('');
|
|
299
|
+
info('Multiple databases found in backup:');
|
|
300
|
+
userDatabases.forEach(db => info(` - ${db}`));
|
|
301
|
+
info('');
|
|
302
|
+
const { selectedDb } = yield prompt.ask({
|
|
303
|
+
choices: userDatabases,
|
|
304
|
+
initial: 0,
|
|
305
|
+
message: 'Select source database to restore:',
|
|
306
|
+
name: 'selectedDb',
|
|
307
|
+
type: 'select',
|
|
308
|
+
});
|
|
309
|
+
if (!selectedDb) {
|
|
310
|
+
error('No database selected');
|
|
311
|
+
// Cleanup
|
|
312
|
+
try {
|
|
313
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
// Ignore cleanup errors
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
sourceDbName = selectedDb;
|
|
321
|
+
success(`Selected source database: ${sourceDbName}`);
|
|
322
|
+
}
|
|
323
|
+
info(`Backup root directory: ${backupRootDir}`);
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
error(`Could not detect databases: ${err.message}`);
|
|
327
|
+
// Cleanup
|
|
328
|
+
try {
|
|
329
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
330
|
+
}
|
|
331
|
+
catch (e) {
|
|
332
|
+
// Ignore cleanup errors
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// ============================================================================
|
|
337
|
+
// Step 7: MongoDB Configuration
|
|
338
|
+
// ============================================================================
|
|
339
|
+
info('');
|
|
340
|
+
info('Step 7: MongoDB Configuration');
|
|
341
|
+
info('');
|
|
342
|
+
const mongoUri = yield helper.getInput(parameters.options.mongoUri || process.env.MONGO_URI || 'mongodb://127.0.0.1:27017', {
|
|
343
|
+
initial: 'mongodb://127.0.0.1:27017',
|
|
344
|
+
name: 'MongoDB Connection URI (without database name)',
|
|
345
|
+
showError: true,
|
|
346
|
+
});
|
|
347
|
+
if (!mongoUri) {
|
|
348
|
+
error('MongoDB URI is required');
|
|
349
|
+
// Cleanup
|
|
350
|
+
try {
|
|
351
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
352
|
+
}
|
|
353
|
+
catch (e) {
|
|
354
|
+
// Ignore cleanup errors
|
|
355
|
+
}
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const targetDbName = yield helper.getInput(parameters.options.database || sourceDbName, {
|
|
359
|
+
initial: sourceDbName,
|
|
360
|
+
name: 'Target Database Name',
|
|
361
|
+
showError: true,
|
|
362
|
+
});
|
|
363
|
+
if (!targetDbName) {
|
|
364
|
+
error('Target database name is required');
|
|
365
|
+
// Cleanup
|
|
366
|
+
try {
|
|
367
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
368
|
+
}
|
|
369
|
+
catch (e) {
|
|
370
|
+
// Ignore cleanup errors
|
|
371
|
+
}
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
// ============================================================================
|
|
375
|
+
// Step 8: Confirmation
|
|
376
|
+
// ============================================================================
|
|
377
|
+
info('');
|
|
378
|
+
warning('IMPORTANT: This operation will restore the backup to the target database.');
|
|
379
|
+
warning(`Target: ${mongoUri}/${targetDbName}`);
|
|
380
|
+
warning('If the database already exists, it may be overwritten or merged.');
|
|
381
|
+
info('');
|
|
382
|
+
const { confirmRestore } = yield prompt.ask({
|
|
383
|
+
initial: false,
|
|
384
|
+
message: `Proceed with restore to ${targetDbName}?`,
|
|
385
|
+
name: 'confirmRestore',
|
|
386
|
+
type: 'confirm',
|
|
387
|
+
});
|
|
388
|
+
if (!confirmRestore) {
|
|
389
|
+
info('Restore cancelled');
|
|
390
|
+
// Cleanup
|
|
391
|
+
try {
|
|
392
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
393
|
+
}
|
|
394
|
+
catch (e) {
|
|
395
|
+
// Ignore cleanup errors
|
|
396
|
+
}
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Step 9: Restore Database
|
|
401
|
+
// ============================================================================
|
|
402
|
+
info('');
|
|
403
|
+
info('Step 9: Restoring database...');
|
|
404
|
+
info('');
|
|
405
|
+
try {
|
|
406
|
+
const restoreSpin = spin(`Restoring ${sourceDbName} to ${targetDbName}`);
|
|
407
|
+
// Build mongorestore command
|
|
408
|
+
// If source and target names are the same, use simpler command
|
|
409
|
+
let restoreCommand;
|
|
410
|
+
if (sourceDbName === targetDbName) {
|
|
411
|
+
// Restore without renaming
|
|
412
|
+
const fullMongoUri = `${mongoUri}/${targetDbName}`;
|
|
413
|
+
restoreCommand = `mongorestore --uri="${fullMongoUri}" --nsInclude="${sourceDbName}.*" "${backupRootDir}"`;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
// Restore with renaming using --nsFrom and --nsTo
|
|
417
|
+
restoreCommand = `mongorestore --uri="${mongoUri}" --nsFrom="${sourceDbName}.*" --nsTo="${targetDbName}.*" --nsInclude="${sourceDbName}.*" "${backupRootDir}"`;
|
|
418
|
+
}
|
|
419
|
+
info('Running: mongorestore ...');
|
|
420
|
+
const { stderr } = yield execAsync(restoreCommand, {
|
|
421
|
+
maxBuffer: 1024 * 1024 * 50, // 50MB buffer for large outputs
|
|
422
|
+
});
|
|
423
|
+
// Check for actual failures (mongorestore outputs warnings to stderr)
|
|
424
|
+
if (stderr && stderr.includes('Failed:') && !stderr.includes('0 document(s) failed')) {
|
|
425
|
+
throw new Error(stderr);
|
|
426
|
+
}
|
|
427
|
+
restoreSpin.succeed(`Database restored successfully (${sourceDbName} → ${targetDbName})`);
|
|
428
|
+
}
|
|
429
|
+
catch (err) {
|
|
430
|
+
error(`Failed to restore database: ${err.message}`);
|
|
431
|
+
info('');
|
|
432
|
+
info('Please ensure:');
|
|
433
|
+
info('- MongoDB is running and accessible');
|
|
434
|
+
info('- mongorestore tool is installed (part of MongoDB Database Tools)');
|
|
435
|
+
info('- The MongoDB URI is correct');
|
|
436
|
+
info('- The source database exists in the backup');
|
|
437
|
+
// Cleanup
|
|
438
|
+
try {
|
|
439
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
440
|
+
}
|
|
441
|
+
catch (e) {
|
|
442
|
+
// Ignore cleanup errors
|
|
443
|
+
}
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
// ============================================================================
|
|
447
|
+
// Step 10: Cleanup
|
|
448
|
+
// ============================================================================
|
|
449
|
+
info('');
|
|
450
|
+
const cleanupSpin = spin('Cleaning up temporary files');
|
|
451
|
+
try {
|
|
452
|
+
yield fs.promises.rm(tempDir, { force: true, recursive: true });
|
|
453
|
+
cleanupSpin.succeed('Temporary files cleaned up');
|
|
454
|
+
}
|
|
455
|
+
catch (err) {
|
|
456
|
+
cleanupSpin.fail(`Failed to cleanup temporary files: ${err.message}`);
|
|
457
|
+
warning(`You may need to manually delete: ${tempDir}`);
|
|
458
|
+
}
|
|
459
|
+
// ============================================================================
|
|
460
|
+
// Done
|
|
461
|
+
// ============================================================================
|
|
462
|
+
info('');
|
|
463
|
+
success(`Database restored successfully to ${targetDbName} in ${helper.msToMinutesAndSeconds(timer())}m`);
|
|
464
|
+
info('');
|
|
465
|
+
if (!parameters.options.fromGluegunMenu) {
|
|
466
|
+
process.exit(0);
|
|
467
|
+
}
|
|
468
|
+
return `mongodb restored ${targetDbName}`;
|
|
469
|
+
}),
|
|
470
|
+
};
|
|
471
|
+
exports.default = command;
|
|
472
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiczMtcmVzdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9tb25nb2RiL3MzLXJlc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsa0RBQStEO0FBQy9ELHlCQUF5QjtBQUV6Qiw2QkFBNkI7QUFDN0IsK0JBQWlDO0FBSWpDLE1BQU0sU0FBUyxHQUFHLElBQUEsZ0JBQVMsRUFBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7QUFTM0Q7O0dBRUc7QUFDSCxNQUFNLE9BQU8sR0FBbUI7SUFDOUIsS0FBSyxFQUFFLENBQUMsS0FBSyxDQUFDO0lBQ2QsV0FBVyxFQUFFLHlDQUF5QztJQUN0RCxJQUFJLEVBQUUsWUFBWTtJQUNsQixHQUFHLEVBQUUsQ0FBTyxPQUErQixFQUFFLEVBQUU7O1FBQzdDLE1BQU0sRUFDSixNQUFNLEVBQ04sVUFBVSxFQUNWLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFDOUMsTUFBTSxFQUNOLE1BQU0sR0FDUCxHQUFHLE9BQU8sQ0FBQztRQUVaLGNBQWM7UUFDZCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFbEMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRVQsK0VBQStFO1FBQy9FLDJCQUEyQjtRQUMzQiwrRUFBK0U7UUFFL0UsSUFBSSxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRVQsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFO1lBQ3pGLElB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.124",
|
|
4
4
|
"description": "lenne.Tech CLI: lt",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lenne.Tech",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"bin"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
+
"@aws-sdk/client-s3": "3.908.0",
|
|
52
53
|
"@lenne.tech/cli-plugin-helper": "0.0.13",
|
|
53
54
|
"bcrypt": "6.0.0",
|
|
54
55
|
"find-file-up": "2.0.1",
|
|
@@ -57,26 +58,26 @@
|
|
|
57
58
|
"js-sha256": "0.11.1",
|
|
58
59
|
"open": "10.2.0",
|
|
59
60
|
"standard-version": "9.5.0",
|
|
60
|
-
"ts-morph": "
|
|
61
|
+
"ts-morph": "27.0.0",
|
|
61
62
|
"ts-node": "10.9.2",
|
|
62
|
-
"typescript": "5.9.
|
|
63
|
+
"typescript": "5.9.3"
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
66
|
"@lenne.tech/eslint-config-ts": "2.1.3",
|
|
66
67
|
"@lenne.tech/npm-package-helper": "0.0.12",
|
|
67
68
|
"@types/jest": "30.0.0",
|
|
68
|
-
"@types/node": "24.
|
|
69
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
70
|
-
"@typescript-eslint/parser": "8.
|
|
71
|
-
"eslint": "9.
|
|
69
|
+
"@types/node": "24.7.2",
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "8.46.0",
|
|
71
|
+
"@typescript-eslint/parser": "8.46.0",
|
|
72
|
+
"eslint": "9.37.0",
|
|
72
73
|
"eslint-config-prettier": "10.1.8",
|
|
73
74
|
"husky": "9.1.7",
|
|
74
|
-
"jest": "30.0
|
|
75
|
+
"jest": "30.2.0",
|
|
75
76
|
"path-exists-cli": "2.0.0",
|
|
76
77
|
"prettier": "3.6.2",
|
|
77
78
|
"pretty-quick": "4.2.2",
|
|
78
79
|
"rimraf": "6.0.1",
|
|
79
|
-
"ts-jest": "29.4.
|
|
80
|
+
"ts-jest": "29.4.5"
|
|
80
81
|
},
|
|
81
82
|
"overrides": {
|
|
82
83
|
"apisauce@*": "3.1.1",
|