Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions src/cli/interactive.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,42 @@
import readline from 'readline';

const interactive = () => {
// Write your code here
// Use readline module for interactive CLI
// Support commands: uptime, cwd, date, exit
// Handle Ctrl+C and unknown commands
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: '> ',
});

rl.prompt();

rl.on('line', (line) => {
const command = line.trim();

switch (command) {
case 'uptime':
console.log(`Uptime: ${process.uptime().toFixed(2)}s`);
break;
case 'cwd':
console.log(process.cwd());
break;
case 'date':
console.log(new Date().toISOString());
break;
case 'exit':
console.log('Goodbye!');
process.exit(0);
break;
default:
console.log('Unknown command');
}

rl.prompt();
});

rl.on('close', () => {
console.log('Goodbye!');
process.exit(0);
});
};

interactive();
61 changes: 57 additions & 4 deletions src/cli/progress.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,61 @@
const args = process.argv.slice(2);

const RESET = '\x1b[0m';

const getArg = (name) => {
const index = args.indexOf(name);
if (index === -1 || index + 1 >= args.length) return undefined;
return args[index + 1];
};

const getNumericArg = (name, defaultValue) => {
const raw = getArg(name);
if (raw === undefined) return defaultValue;
const parsed = parseInt(raw, 10);
return Number.isNaN(parsed) ? defaultValue : parsed;
};

const parseHexColor = (hex) => {
if (!hex) return null;
const match = hex.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);
if (!match) return null;
const r = parseInt(match[1], 16);
const g = parseInt(match[2], 16);
const b = parseInt(match[3], 16);
return `\x1b[38;2;${r};${g};${b}m`;
};

const renderBar = (percent, length, colorCode) => {
const filled = Math.round((percent / 100) * length);
const empty = length - filled;

const filledBar = '█'.repeat(filled);
const emptyBar = ' '.repeat(empty);

const coloredFilled = colorCode ? `${colorCode}${filledBar}${RESET}` : filledBar;
return `[${coloredFilled}${emptyBar}] ${percent}%`;
};

const progress = () => {
// Write your code here
// Simulate progress bar from 0% to 100% over ~5 seconds
// Update in place using \r every 100ms
// Format: [████████████████████ ] 67%
const duration = getNumericArg('--duration', 5000);
const interval = getNumericArg('--interval', 100);
const length = getNumericArg('--length', 30);
const colorCode = parseHexColor(getArg('--color'));

const totalSteps = Math.ceil(duration / interval);
let currentStep = 0;

const timer = setInterval(() => {
currentStep++;
const percent = Math.min(Math.round((currentStep / totalSteps) * 100), 100);

process.stdout.write(`\r${renderBar(percent, length, colorCode)}`);

if (currentStep >= totalSteps) {
clearInterval(timer);
process.stdout.write('\nDone!\n');
}
}, interval);
};

progress();
65 changes: 59 additions & 6 deletions src/fs/snapshot.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,62 @@
import { promises as fs } from 'fs';
import path from 'path';

async function scanDirectory(dirPath, relativePath = '') {
try {
const entries = [];
const items = await fs.readdir(dirPath);
items.sort();

for (const item of items) {
const fullPath = path.join(dirPath, item);
const relPath = path.join(relativePath, item);
const stats = await fs.stat(fullPath);

if (stats.isDirectory()) {
entries.push({ path: relPath, type: 'directory' });
const subEntries = await scanDirectory(fullPath, relPath);
entries.push(...subEntries);
} else if (stats.isFile()) {
const buffer = await fs.readFile(fullPath);
entries.push({
path: relPath,
type: 'file',
size: stats.size,
content: buffer.toString('base64'),
});
}
}

return entries;
} catch (error) {
throw new Error(`FS operation failed: ${error.message}`);
}
}

const snapshot = async () => {
// Write your code here
// Recursively scan workspace directory
// Write snapshot.json with:
// - rootPath: absolute path to workspace
// - entries: flat array of relative paths and metadata
const workspacePath = path.join(process.cwd(), 'workspace');
try {
await fs.access(workspacePath);
} catch (error) {
throw new Error(`FS operation failed: ${error.message}`);
}

const entries = await scanDirectory(workspacePath);

const result = {
rootPath: workspacePath,
entries,
};

const snapshotPath = path.join(path.dirname(workspacePath), 'snapshot.json');
try {
await fs.writeFile(snapshotPath, JSON.stringify(result, null, 2));
} catch (error) {
throw new Error(`FS operation failed: ${error.message}`);
}
};

await snapshot();
await snapshot().catch((error) => {
console.error(error.message);
process.exit(1);
});
14 changes: 9 additions & 5 deletions src/modules/dynamic.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
const dynamic = async () => {
// Write your code here
// Accept plugin name as CLI argument
// Dynamically import plugin from plugins/ directory
// Call run() function and print result
// Handle missing plugin case
const args = process.argv.slice(2);
const pluginName = args.at(-1);
try {
const plugin = await import(`./plugins/${pluginName}.js`);
console.log(plugin.run());
} catch (error) {
console.error(`Plugin not found`);
process.exit(1);
}
};

await dynamic();
25 changes: 21 additions & 4 deletions src/streams/lineNumberer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import { Transform } from 'node:stream';

const addLineNumbers = (chunk, counter) =>
chunk
.toString()
.split('\n')
.map((line, i) => {
if (i === 0 && line === '') return '';
return `${counter.value++} | ${line}`;
})
.join('\n');

const counter = { value: 1 };

const transform = new Transform({
transform(chunk, enc, cb) {
cb(null, addLineNumbers(chunk, counter));
},
});

const lineNumberer = () => {
// Write your code here
// Read from process.stdin
// Use Transform Stream to prepend line numbers
// Write to process.stdout
process.stdin.pipe(transform).pipe(process.stdout);
};

lineNumberer();