UNPKG

@lenne.tech/cli

Version:

lenne.Tech CLI: lt

287 lines (286 loc) 12.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const util_1 = require("util"); const execAsync = (0, util_1.promisify)(require('child_process').exec); /** * Export MongoDB collection to JSON file */ const command = { alias: ['ce'], description: 'Export collection to JSON', name: 'collection-export', run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () { const { helper, parameters, print: { error, info, spin, success, warning }, prompt, system, } = toolbox; // Start timer const timer = system.startTimer(); info('MongoDB Collection Export'); info(''); // ============================================================================ // Step 1: MongoDB Connection // ============================================================================ info('Step 1: MongoDB Connection'); info(''); const mongoUri = yield helper.getInput(parameters.options.mongoUri || process.env.MONGO_URI || 'mongodb://127.0.0.1:27017', { initial: 'mongodb://127.0.0.1:27017', name: 'MongoDB Connection URI', showError: true, }); if (!mongoUri) { error('MongoDB URI is required'); return; } // ============================================================================ // Step 2: List Databases // ============================================================================ info(''); info('Step 2: Fetching databases...'); info(''); let databases = []; const systemDatabases = ['admin', 'local', 'config']; try { const listDbSpin = spin('Listing databases'); // Use mongo shell to list databases const listDbCommand = `mongosh "${mongoUri}" --quiet --eval "JSON.stringify(db.adminCommand('listDatabases').databases.map(d => d.name))"`; const { stdout } = yield execAsync(listDbCommand); const allDatabases = JSON.parse(stdout.trim()); // Filter out system databases databases = allDatabases.filter((db) => !systemDatabases.includes(db)); if (databases.length === 0) { listDbSpin.fail('No user databases found'); warning('Only system databases (admin, local, config) are available'); return; } listDbSpin.succeed(`Found ${databases.length} database(s)`); } catch (err) { error(`Failed to list databases: ${err.message}`); info(''); info('Please ensure:'); info('- MongoDB is running and accessible'); info('- mongosh (MongoDB Shell) is installed'); info('- The MongoDB URI is correct'); return; } // ============================================================================ // Step 3: Select Database // ============================================================================ info(''); info('Step 3: Select database'); info(''); let selectedDatabase; if (parameters.options.database) { selectedDatabase = parameters.options.database; if (!databases.includes(selectedDatabase)) { error(`Database "${selectedDatabase}" not found`); return; } success(`Using database: ${selectedDatabase}`); } else { const { database } = yield prompt.ask({ choices: databases, initial: 0, message: 'Select database:', name: 'database', type: 'select', }); if (!database) { error('No database selected'); return; } selectedDatabase = database; success(`Selected database: ${selectedDatabase}`); } // ============================================================================ // Step 4: List Collections // ============================================================================ info(''); info('Step 4: Fetching collections...'); info(''); let collections = []; try { const listCollSpin = spin('Listing collections'); // Use mongo shell to list collections const listCollCommand = `mongosh "${mongoUri}/${selectedDatabase}" --quiet --eval "JSON.stringify(db.getCollectionNames())"`; const { stdout } = yield execAsync(listCollCommand); collections = JSON.parse(stdout.trim()); if (collections.length === 0) { listCollSpin.fail('No collections found in this database'); return; } listCollSpin.succeed(`Found ${collections.length} collection(s)`); } catch (err) { error(`Failed to list collections: ${err.message}`); return; } // ============================================================================ // Step 5: Select Collection // ============================================================================ info(''); info('Step 5: Select collection'); info(''); let selectedCollection; if (parameters.options.collection) { selectedCollection = parameters.options.collection; if (!collections.includes(selectedCollection)) { error(`Collection "${selectedCollection}" not found`); return; } success(`Using collection: ${selectedCollection}`); } else { const { collection } = yield prompt.ask({ choices: collections, initial: 0, message: 'Select collection:', name: 'collection', type: 'select', }); if (!collection) { error('No collection selected'); return; } selectedCollection = collection; success(`Selected collection: ${selectedCollection}`); } // Get document count try { const countCommand = `mongosh "${mongoUri}/${selectedDatabase}" --quiet --eval "db.${selectedCollection}.countDocuments()"`; const { stdout } = yield execAsync(countCommand); const count = parseInt(stdout.trim(), 10); info(`Collection contains ${count} document(s)`); } catch (err) { warning(`Could not get document count: ${err.message}`); } // ============================================================================ // Step 6: Output File Path // ============================================================================ info(''); info('Step 6: Output file path'); info(''); const defaultFilename = `${selectedDatabase}_${selectedCollection}_${Date.now()}.json`; const defaultPath = path.join(process.cwd(), defaultFilename); const outputPath = yield helper.getInput(parameters.options.output || defaultPath, { initial: defaultPath, name: 'Output file path', showError: true, }); if (!outputPath) { error('Output path is required'); return; } // Check if file exists if (yield toolbox.filesystem.existsAsync(outputPath)) { const { overwrite } = yield prompt.ask({ initial: false, message: `File "${outputPath}" already exists. Overwrite?`, name: 'overwrite', type: 'confirm', }); if (!overwrite) { info('Export cancelled'); return; } } // Ensure directory exists const outputDir = path.dirname(outputPath); try { yield fs.promises.mkdir(outputDir, { recursive: true }); } catch (err) { error(`Failed to create directory: ${err.message}`); return; } // ============================================================================ // Step 7: Export Data // ============================================================================ info(''); info('Step 7: Exporting data...'); info(''); try { const exportSpin = spin(`Exporting ${selectedDatabase}.${selectedCollection}`); // Use mongoexport to export collection const exportCommand = `mongoexport --uri="${mongoUri}/${selectedDatabase}" --collection="${selectedCollection}" --out="${outputPath}" --jsonArray`; const { stderr } = yield execAsync(exportCommand, { maxBuffer: 1024 * 1024 * 100, // 100MB buffer }); // mongoexport outputs progress to stderr, check for actual errors if (stderr && stderr.toLowerCase().includes('error') && !stderr.includes('exported')) { throw new Error(stderr); } exportSpin.succeed('Data exported successfully'); // Get file size const stats = yield fs.promises.stat(outputPath); const fileSizeMB = (stats.size / 1024 / 1024).toFixed(2); info(`File size: ${fileSizeMB} MB`); } catch (err) { error(`Failed to export data: ${err.message}`); info(''); info('Please ensure:'); info('- MongoDB is running and accessible'); info('- mongoexport tool is installed (part of MongoDB Database Tools)'); info('- You have read permissions on the database/collection'); info('- You have write permissions to the output directory'); return; } // ============================================================================ // Done // ============================================================================ info(''); success(`Collection exported successfully in ${helper.msToMinutesAndSeconds(timer())}m`); success(`Output: ${outputPath}`); info(''); if (!parameters.options.fromGluegunMenu) { process.exit(0); } return `mongodb export ${selectedDatabase}.${selectedCollection}`; }), }; exports.default = command;