Learn Node.js fundamentals including event loop, asynchronous programming, modules, and file system operations.
Learn Node.js fundamentals including event loop, asynchronous programming, modules, and file system operations.
Understanding Node.js architecture, runtime environment, and its role in modern web development
Content by: Umesh Dangar
MERN Stack Developer
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It allows you to run JavaScript on the server-side, enabling full-stack JavaScript development. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.
// Check Node.js version
node --version
// Check NPM version
npm --version
// Create a new Node.js project
mkdir my-node-app
cd my-node-app
npm init -y
// Install dependencies
npm install express
// Basic Node.js server
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World!');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});// Essential development tools for Node.js
// 1. Node Version Manager (NVM)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 18
nvm use 18
// 2. Package.json configuration
{
"name": "my-node-app",
"version": "1.0.0",
"description": "A Node.js application",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest"
},
"keywords": ["nodejs", "javascript"],
"author": "Your Name",
"license": "MIT"
}
// 3. Essential NPM packages
npm install express cors helmet morgan
npm install --save-dev nodemon jest supertest
// 4. Environment configuration
// .env file
PORT=3000
NODE_ENV=development
DATABASE_URL=mongodb://localhost:27017/myapp
// Load environment variables
require('dotenv').config();// Create a comprehensive Hello World server with multiple endpoints
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
const method = req.method;
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Content-Type', 'application/json');
// Route handling
if (path === '/' && method === 'GET') {
res.writeHead(200);
res.end(JSON.stringify({
message: 'Hello World!',
timestamp: new Date().toISOString(),
method: method,
path: path
}));
} else if (path === '/health' && method === 'GET') {
res.writeHead(200);
res.end(JSON.stringify({
status: 'healthy',
uptime: process.uptime(),
memory: process.memoryUsage()
}));
} else if (path === '/echo' && method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
res.writeHead(200);
res.end(JSON.stringify({
message: 'Echo response',
received: body,
timestamp: new Date().toISOString()
}));
});
} else {
res.writeHead(404);
res.end(JSON.stringify({
error: 'Not Found',
message: 'The requested resource was not found'
}));
}
});
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/`);
console.log('Available endpoints:');
console.log(' GET / - Hello World');
console.log(' GET /health - Health check');
console.log(' POST /echo - Echo back request body');
});
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down gracefully');
server.close(() => {
console.log('Process terminated');
});
});Test your understanding of this topic:
Master Node.js event loop and asynchronous programming patterns with callbacks, promises, and async/await
Content by: Meena Chauhan
Node.js Developer
The event loop is the core of Node.js's asynchronous, non-blocking I/O model. It allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded. The event loop continuously checks for pending operations and executes them when they're ready.
// Callback pattern
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File content:', data);
});
// Promise pattern
const fs = require('fs').promises;
fs.readFile('file.txt', 'utf8')
.then(data => {
console.log('File content:', data);
})
.catch(err => {
console.error('Error reading file:', err);
});
// Async/await pattern
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('file.txt', 'utf8');
console.log('File content:', data);
} catch (err) {
console.error('Error reading file:', err);
}
}
readFile();
// Event emitter pattern
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (arg) => {
console.log('Event occurred with argument:', arg);
});
myEmitter.emit('event', 'Hello World!');// Performance comparison of different async patterns
const fs = require('fs').promises;
const path = require('path');
// Sequential execution (slower)
async function readFilesSequentially() {
const start = Date.now();
const file1 = await fs.readFile('file1.txt', 'utf8');
const file2 = await fs.readFile('file2.txt', 'utf8');
const file3 = await fs.readFile('file3.txt', 'utf8');
const end = Date.now();
console.log('Sequential time:', end - start, 'ms');
return [file1, file2, file3];
}
// Parallel execution (faster)
async function readFilesParallel() {
const start = Date.now();
const [file1, file2, file3] = await Promise.all([
fs.readFile('file1.txt', 'utf8'),
fs.readFile('file2.txt', 'utf8'),
fs.readFile('file3.txt', 'utf8')
]);
const end = Date.now();
console.log('Parallel time:', end - start, 'ms');
return [file1, file2, file3];
}
// Error handling in async operations
async function robustFileOperation() {
try {
const data = await fs.readFile('file.txt', 'utf8');
return data;
} catch (error) {
if (error.code === 'ENOENT') {
console.log('File not found, creating default content');
return 'Default content';
}
throw error; // Re-throw if it's not a file not found error
}
}// Create a file processor that handles multiple async operations
const fs = require('fs').promises;
const path = require('path');
class AsyncFileProcessor {
constructor(inputDir, outputDir) {
this.inputDir = inputDir;
this.outputDir = outputDir;
}
async processFiles() {
try {
// Read all files in input directory
const files = await fs.readdir(this.inputDir);
console.log('Found files:', files);
// Process files in parallel
const results = await Promise.all(
files.map(file => this.processFile(file))
);
// Generate summary report
await this.generateReport(results);
console.log('All files processed successfully');
return results;
} catch (error) {
console.error('Error processing files:', error);
throw error;
}
}
async processFile(filename) {
const inputPath = path.join(this.inputDir, filename);
const outputPath = path.join(this.outputDir, `processed_${filename}`);
try {
// Read file content
const content = await fs.readFile(inputPath, 'utf8');
// Process content (example: convert to uppercase)
const processedContent = content.toUpperCase();
// Write processed content
await fs.writeFile(outputPath, processedContent);
return {
filename,
originalSize: content.length,
processedSize: processedContent.length,
status: 'success'
};
} catch (error) {
return {
filename,
error: error.message,
status: 'error'
};
}
}
async generateReport(results) {
const report = {
timestamp: new Date().toISOString(),
totalFiles: results.length,
successful: results.filter(r => r.status === 'success').length,
failed: results.filter(r => r.status === 'error').length,
results: results
};
const reportPath = path.join(this.outputDir, 'processing_report.json');
await fs.writeFile(reportPath, JSON.stringify(report, null, 2));
console.log('Report generated:', reportPath);
}
}
// Usage
async function main() {
const processor = new AsyncFileProcessor('./input', './output');
try {
await processor.processFiles();
} catch (error) {
console.error('Processing failed:', error);
}
}
// Run the processor
main();Test your understanding of this topic:
Learn Node.js module system, CommonJS vs ES modules, and NPM package management
Content by: Raj Koradiya
Node.js Developer
Node.js has a built-in module system that allows you to organize your code into reusable pieces. Modules help you create maintainable and scalable applications by separating concerns and avoiding global scope pollution.
// math.js - Exporting modules
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const multiply = (a, b) => a * b;
const divide = (a, b) => a / b;
// Export individual functions
module.exports.add = add;
module.exports.subtract = subtract;
// Export as an object
module.exports = {
add,
subtract,
multiply,
divide
};
// app.js - Importing modules
const math = require('./math');
console.log(math.add(5, 3)); // 8
console.log(math.subtract(10, 4)); // 6
console.log(math.multiply(2, 6)); // 12
console.log(math.divide(15, 3)); // 5
// Destructuring imports
const { add, subtract } = require('./math');
console.log(add(5, 3)); // 8
console.log(subtract(10, 4)); // 6// math.js - ES Module exports
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
export const divide = (a, b) => a / b;
// Default export
const calculator = {
add,
subtract,
multiply,
divide
};
export default calculator;
// app.js - ES Module imports
import { add, subtract, multiply, divide } from './math.js';
import calculator from './math.js';
console.log(add(5, 3)); // 8
console.log(calculator.multiply(2, 6)); // 12
// Dynamic imports
async function loadModule() {
const math = await import('./math.js');
console.log(math.add(5, 3));
}
loadModule();// Initialize a new project
npm init -y
// Install dependencies
npm install express
npm install --save-dev nodemon
// Install specific version
npm install express@4.18.2
// Install globally
npm install -g nodemon
// Remove package
npm uninstall express
// Update packages
npm update
// List installed packages
npm list
// Run scripts
npm start
npm test
npm run dev
// package.json example
{
"name": "my-node-app",
"version": "1.0.0",
"description": "A Node.js application",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^2.0.22"
}
}// ES Modules (ESM) - Modern approach
// math.mjs
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
// Default export
export default class Calculator {
constructor() {
this.history = [];
}
calculate(operation, a, b) {
const result = operation(a, b);
this.history.push({ operation: operation.name, a, b, result });
return result;
}
}
// app.mjs - Importing ES modules
import { add, subtract } from './math.mjs';
import Calculator from './math.mjs';
const calc = new Calculator();
console.log(calc.calculate(add, 5, 3)); // 8
// CommonJS - Traditional approach
// math.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
module.exports = { add, subtract };
// app.js - Importing CommonJS
const { add, subtract } = require('./math');
console.log(add(5, 3)); // 8
// Using both in the same project
// package.json
{
"type": "module", // Enable ES modules
"scripts": {
"start": "node app.mjs"
}
}// package.json with comprehensive scripts
{
"name": "my-node-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint src/**/*.js",
"lint:fix": "eslint src/**/*.js --fix",
"build": "webpack --mode production",
"build:dev": "webpack --mode development",
"clean": "rimraf dist",
"precommit": "npm run lint && npm run test",
"deploy": "npm run build && npm run test && pm2 start ecosystem.config.js",
"logs": "pm2 logs",
"restart": "pm2 restart all"
},
"dependencies": {
"express": "^4.18.2",
"cors": "^2.8.5",
"helmet": "^6.0.1"
},
"devDependencies": {
"nodemon": "^2.0.22",
"jest": "^29.0.0",
"eslint": "^8.0.0",
"webpack": "^5.0.0",
"rimraf": "^3.0.2",
"pm2": "^5.0.0"
}
}
// Custom script example
// scripts/setup.js
import fs from 'fs';
import path from 'path';
const setupProject = () => {
const dirs = ['src', 'tests', 'docs', 'logs'];
dirs.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(`Created directory: ${dir}`);
}
});
// Create basic files
const files = {
'src/index.js': 'console.log("Hello from Node.js!");',
'tests/index.test.js': 'import { test } from "jest";
test("basic test", () => {
expect(1 + 1).toBe(2);
});',
'.gitignore': 'node_modules/
.env
logs/
dist/',
'.env.example': 'PORT=3000
NODE_ENV=development'
};
Object.entries(files).forEach(([filePath, content]) => {
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, content);
console.log(`Created file: ${filePath}`);
}
});
console.log('Project setup complete!');
};
setupProject();// Create a comprehensive calculator using modules
// src/calculator/operations.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
export const divide = (a, b) => {
if (b === 0) throw new Error('Division by zero');
return a / b;
};
export const power = (a, b) => Math.pow(a, b);
export const sqrt = (a) => {
if (a < 0) throw new Error('Square root of negative number');
return Math.sqrt(a);
};
// src/calculator/history.js
class History {
constructor() {
this.operations = [];
}
add(operation, a, b, result) {
this.operations.push({
id: Date.now(),
operation,
operands: { a, b },
result,
timestamp: new Date().toISOString()
});
}
getAll() {
return this.operations;
}
getLast(n = 5) {
return this.operations.slice(-n);
}
clear() {
this.operations = [];
}
export() {
return JSON.stringify(this.operations, null, 2);
}
}
export default History;
// src/calculator/validator.js
export const validateNumber = (num) => {
if (typeof num !== 'number' || isNaN(num)) {
throw new Error('Invalid number provided');
}
return true;
};
export const validateOperation = (op) => {
const validOps = ['add', 'subtract', 'multiply', 'divide', 'power', 'sqrt'];
if (!validOps.includes(op)) {
throw new Error(`Invalid operation: ${op}`);
}
return true;
};
// src/calculator/index.js
import * as operations from './operations.js';
import History from './history.js';
import { validateNumber, validateOperation } from './validator.js';
class Calculator {
constructor() {
this.history = new History();
}
calculate(operation, a, b = null) {
try {
validateOperation(operation);
validateNumber(a);
if (b !== null) validateNumber(b);
let result;
switch (operation) {
case 'add':
result = operations.add(a, b);
break;
case 'subtract':
result = operations.subtract(a, b);
break;
case 'multiply':
result = operations.multiply(a, b);
break;
case 'divide':
result = operations.divide(a, b);
break;
case 'power':
result = operations.power(a, b);
break;
case 'sqrt':
result = operations.sqrt(a);
break;
}
this.history.add(operation, a, b, result);
return result;
} catch (error) {
console.error('Calculation error:', error.message);
throw error;
}
}
getHistory() {
return this.history.getAll();
}
getLastOperations(n = 5) {
return this.history.getLast(n);
}
clearHistory() {
this.history.clear();
}
exportHistory() {
return this.history.export();
}
}
export default Calculator;
// src/index.js - Main application
import Calculator from './calculator/index.js';
const calc = new Calculator();
// Example usage
try {
console.log('Calculator Demo');
console.log('==============');
console.log('5 + 3 =', calc.calculate('add', 5, 3));
console.log('10 - 4 =', calc.calculate('subtract', 10, 4));
console.log('6 * 7 =', calc.calculate('multiply', 6, 7));
console.log('15 / 3 =', calc.calculate('divide', 15, 3));
console.log('2 ^ 8 =', calc.calculate('power', 2, 8));
console.log('√16 =', calc.calculate('sqrt', 16));
console.log('\nLast 3 operations:');
console.log(calc.getLastOperations(3));
console.log('\nFull history:');
console.log(calc.exportHistory());
} catch (error) {
console.error('Error:', error.message);
}Test your understanding of this topic:
Learn to work with files and directories using Node.js fs module
Content by: Neel Bhavsar
Node.js Developer
The fs module provides an API for interacting with the file system. It supports both synchronous and asynchronous operations, with the asynchronous versions being preferred for better performance.
const fs = require('fs');
// Synchronous file reading
try {
const data = fs.readFileSync('file.txt', 'utf8');
console.log('File content:', data);
} catch (err) {
console.error('Error reading file:', err);
}
// Asynchronous file reading
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File content:', data);
});
// Using promises
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('file.txt', 'utf8');
console.log('File content:', data);
} catch (err) {
console.error('Error reading file:', err);
}
}
readFile();
// Reading JSON files
const fs = require('fs').promises;
async function readJSON() {
try {
const data = await fs.readFile('config.json', 'utf8');
const config = JSON.parse(data);
console.log('Config:', config);
} catch (err) {
console.error('Error reading JSON:', err);
}
}
readJSON();const fs = require('fs');
// Synchronous file writing
try {
fs.writeFileSync('output.txt', 'Hello World!');
console.log('File written successfully');
} catch (err) {
console.error('Error writing file:', err);
}
// Asynchronous file writing
fs.writeFile('output.txt', 'Hello World!', (err) => {
if (err) {
console.error('Error writing file:', err);
return;
}
console.log('File written successfully');
});
// Using promises
const fs = require('fs').promises;
async function writeFile() {
try {
await fs.writeFile('output.txt', 'Hello World!');
console.log('File written successfully');
} catch (err) {
console.error('Error writing file:', err);
}
}
writeFile();
// Appending to files
const fs = require('fs').promises;
async function appendToFile() {
try {
await fs.appendFile('log.txt', 'New log entry\n');
console.log('Log entry added');
} catch (err) {
console.error('Error appending to file:', err);
}
}
appendToFile();
// Writing JSON files
const fs = require('fs').promises;
async function writeJSON() {
const data = {
name: 'John Doe',
age: 30,
city: 'New York'
};
try {
await fs.writeFile('user.json', JSON.stringify(data, null, 2));
console.log('JSON file written successfully');
} catch (err) {
console.error('Error writing JSON:', err);
}
}
writeJSON();const fs = require('fs');
// Creating directories
fs.mkdir('new-directory', (err) => {
if (err) {
console.error('Error creating directory:', err);
return;
}
console.log('Directory created successfully');
});
// Reading directory contents
fs.readdir('.', (err, files) => {
if (err) {
console.error('Error reading directory:', err);
return;
}
console.log('Files in directory:', files);
});
// Checking if file/directory exists
fs.access('file.txt', fs.constants.F_OK, (err) => {
if (err) {
console.log('File does not exist');
} else {
console.log('File exists');
}
});
// Getting file stats
fs.stat('file.txt', (err, stats) => {
if (err) {
console.error('Error getting file stats:', err);
return;
}
console.log('File size:', stats.size);
console.log('Is file:', stats.isFile());
console.log('Is directory:', stats.isDirectory());
console.log('Created:', stats.birthtime);
console.log('Modified:', stats.mtime);
});
// Using promises for directory operations
const fs = require('fs').promises;
async function directoryOperations() {
try {
// Create directory
await fs.mkdir('new-directory');
console.log('Directory created');
// Read directory
const files = await fs.readdir('.');
console.log('Files:', files);
// Check if file exists
try {
await fs.access('file.txt');
console.log('File exists');
} catch {
console.log('File does not exist');
}
// Get file stats
const stats = await fs.stat('file.txt');
console.log('File size:', stats.size);
} catch (err) {
console.error('Error:', err);
}
}
directoryOperations();// Advanced file operations with streams and buffers
const fs = require('fs');
const path = require('path');
// Working with file streams for large files
const readStream = fs.createReadStream('large-file.txt', { encoding: 'utf8' });
const writeStream = fs.createWriteStream('output.txt');
readStream.on('data', (chunk) => {
console.log('Received chunk:', chunk.length, 'bytes');
writeStream.write(chunk);
});
readStream.on('end', () => {
console.log('File reading completed');
writeStream.end();
});
readStream.on('error', (err) => {
console.error('Error reading file:', err);
});
// Working with buffers
const buffer = Buffer.alloc(1024); // Create a 1KB buffer
const buffer2 = Buffer.from('Hello World', 'utf8');
console.log('Buffer length:', buffer.length);
console.log('Buffer content:', buffer2.toString());
// File watching for real-time updates
const watcher = fs.watch('watch-directory', (eventType, filename) => {
console.log(`Event: ${eventType}, File: ${filename}`);
});
// Clean up watcher after 30 seconds
setTimeout(() => {
watcher.close();
console.log('File watcher closed');
}, 30000);
// Working with symbolic links
fs.symlink('target-file.txt', 'link-file.txt', 'file', (err) => {
if (err) {
console.error('Error creating symlink:', err);
} else {
console.log('Symbolic link created');
}
});// Create a command-line file manager using Node.js
const fs = require('fs').promises;
const path = require('path');
const readline = require('readline');
class FileManager {
constructor() {
this.currentDir = process.cwd();
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
}
async start() {
console.log('File Manager CLI');
console.log('===============');
console.log(`Current directory: ${this.currentDir}`);
while (true) {
const command = await this.getInput('> ');
await this.executeCommand(command);
}
}
async getInput(prompt) {
return new Promise((resolve) => {
this.rl.question(prompt, resolve);
});
}
async executeCommand(command) {
const [cmd, ...args] = command.trim().split(' ');
try {
switch (cmd.toLowerCase()) {
case 'ls':
case 'list':
await this.listFiles();
break;
case 'cd':
await this.changeDirectory(args[0]);
break;
case 'mkdir':
await this.createDirectory(args[0]);
break;
case 'rm':
await this.removeFile(args[0]);
break;
case 'cat':
await this.readFile(args[0]);
break;
case 'write':
await this.writeFile(args[0], args.slice(1).join(' '));
break;
case 'copy':
await this.copyFile(args[0], args[1]);
break;
case 'move':
await this.moveFile(args[0], args[1]);
break;
case 'info':
await this.fileInfo(args[0]);
break;
case 'find':
await this.findFiles(args[0]);
break;
case 'help':
this.showHelp();
break;
case 'exit':
case 'quit':
console.log('Goodbye!');
this.rl.close();
process.exit(0);
break;
default:
console.log('Unknown command. Type "help" for available commands.');
}
} catch (error) {
console.error('Error:', error.message);
}
}
async listFiles() {
const files = await fs.readdir(this.currentDir);
const fileInfo = await Promise.all(
files.map(async (file) => {
const filePath = path.join(this.currentDir, file);
const stats = await fs.stat(filePath);
return {
name: file,
isDirectory: stats.isDirectory(),
size: stats.size,
modified: stats.mtime
};
})
);
console.log('\nFiles and directories:');
fileInfo.forEach(file => {
const type = file.isDirectory ? '[DIR]' : '[FILE]';
const size = file.isDirectory ? '' : ` (${file.size} bytes)`;
console.log(`${type} ${file.name}${size}`);
});
console.log();
}
async changeDirectory(newDir) {
if (!newDir) {
console.log('Current directory:', this.currentDir);
return;
}
const targetPath = path.resolve(this.currentDir, newDir);
const stats = await fs.stat(targetPath);
if (stats.isDirectory()) {
this.currentDir = targetPath;
console.log('Changed to:', this.currentDir);
} else {
console.log('Not a directory:', newDir);
}
}
async createDirectory(dirName) {
if (!dirName) {
console.log('Please specify directory name');
return;
}
const dirPath = path.join(this.currentDir, dirName);
await fs.mkdir(dirPath);
console.log('Directory created:', dirName);
}
async removeFile(fileName) {
if (!fileName) {
console.log('Please specify file name');
return;
}
const filePath = path.join(this.currentDir, fileName);
const stats = await fs.stat(filePath);
if (stats.isDirectory()) {
await fs.rmdir(filePath);
console.log('Directory removed:', fileName);
} else {
await fs.unlink(filePath);
console.log('File removed:', fileName);
}
}
async readFile(fileName) {
if (!fileName) {
console.log('Please specify file name');
return;
}
const filePath = path.join(this.currentDir, fileName);
const content = await fs.readFile(filePath, 'utf8');
console.log('\nFile content:');
console.log(content);
console.log();
}
async writeFile(fileName, content) {
if (!fileName) {
console.log('Please specify file name');
return;
}
const filePath = path.join(this.currentDir, fileName);
await fs.writeFile(filePath, content);
console.log('File written:', fileName);
}
async copyFile(source, destination) {
if (!source || !destination) {
console.log('Please specify source and destination');
return;
}
const sourcePath = path.join(this.currentDir, source);
const destPath = path.join(this.currentDir, destination);
await fs.copyFile(sourcePath, destPath);
console.log('File copied:', source, '->', destination);
}
async moveFile(source, destination) {
if (!source || !destination) {
console.log('Please specify source and destination');
return;
}
const sourcePath = path.join(this.currentDir, source);
const destPath = path.join(this.currentDir, destination);
await fs.rename(sourcePath, destPath);
console.log('File moved:', source, '->', destination);
}
async fileInfo(fileName) {
if (!fileName) {
console.log('Please specify file name');
return;
}
const filePath = path.join(this.currentDir, fileName);
const stats = await fs.stat(filePath);
console.log('\nFile information:');
console.log('Name:', fileName);
console.log('Type:', stats.isDirectory() ? 'Directory' : 'File');
console.log('Size:', stats.size, 'bytes');
console.log('Created:', stats.birthtime);
console.log('Modified:', stats.mtime);
console.log('Accessed:', stats.atime);
console.log();
}
async findFiles(pattern) {
if (!pattern) {
console.log('Please specify search pattern');
return;
}
const files = await this.searchFiles(this.currentDir, pattern);
console.log('\nFound files:');
files.forEach(file => console.log(file));
console.log();
}
async searchFiles(dir, pattern) {
const files = await fs.readdir(dir);
const results = [];
for (const file of files) {
const filePath = path.join(dir, file);
const stats = await fs.stat(filePath);
if (stats.isDirectory()) {
const subResults = await this.searchFiles(filePath, pattern);
results.push(...subResults);
} else if (file.includes(pattern)) {
results.push(filePath);
}
}
return results;
}
showHelp() {
console.log('\nAvailable commands:');
console.log(' ls, list - List files and directories');
console.log(' cd <dir> - Change directory');
console.log(' mkdir <name> - Create directory');
console.log(' rm <name> - Remove file or directory');
console.log(' cat <file> - Read file content');
console.log(' write <file> <content> - Write to file');
console.log(' copy <src> <dest> - Copy file');
console.log(' move <src> <dest> - Move file');
console.log(' info <file> - Show file information');
console.log(' find <pattern> - Find files');
console.log(' help - Show this help');
console.log(' exit, quit - Exit the program');
console.log();
}
}
// Start the file manager
const fileManager = new FileManager();
fileManager.start().catch(console.error);Test your understanding of this topic:
Continue your learning journey and master the next set of concepts.
Continue to Module 2