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
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
"scripts": {
"fs:snapshot": "node src/fs/snapshot.js",
"fs:restore": "node src/fs/restore.js",
"fs:findByExt": "node src/fs/findByExt.js --ext txt",
"fs:findByExt": "node src/fs/findByExt.js --ext js",
"fs:merge": "node src/fs/merge.js",
"cli:interactive": "node src/cli/interactive.js",
"cli:progress": "node src/cli/progress.js",
"modules:dynamic": "node src/modules/dynamic.js uppercase",
"modules:dynamic": "node src/modules/dynamic.js reverse",
"hash:verify": "node src/hash/verify.js",
"streams:lineNumberer": "echo 'hello\nworld' | node src/streams/lineNumberer.js",
"streams:filter": "echo 'hello\nworld\ntest' | node src/streams/filter.js --pattern test",
Expand Down
1 change: 1 addition & 0 deletions part/textt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Text 1
1 change: 1 addition & 0 deletions part/ttt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jkkdfkjsdjfkjs
32 changes: 32 additions & 0 deletions src/cli/interactive.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,40 @@
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

console.log(
"Help:\n\tuptime — prints process uptime in seconds (e.g. Uptime: 12.34s)\n\tcwd — prints the current working directory\n\tdate — prints the current date and time in ISO format\n\texit — prints Goodbye! and terminates the process",
);

const read = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: "> ",
});
read.prompt();
read.on("line", (line) => {
const command = line.trim();
switch (command) {
case "uptime":
console.log(`\tUptime: ${process.uptime()} seconds`);
break;
case "cwd":
console.log("\t", process.cwd());
break;
case "date":
console.log("\t", new Date());
break;
case "exit":
console.log("\tGoodbye!\n");
read.close();
return;
default:
console.log("Unknown command");
}
});
};

interactive();
63 changes: 62 additions & 1 deletion src/cli/progress.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,69 @@
import readline from "readline";

function hexToAnsi(hex) {
try {
const match = hex.match(/^#([0-9a-f]{6})$/i);
if (!match) return "";

const num = parseInt(match[1], 16);

const r = (num >> 16) & 255;
const g = (num >> 8) & 255;
const b = num & 255;

return `\x1b[38;2;${r};${g};${b}m`;
} catch {
console.error("Invalid hex color code. Use format: '#RRGGBB'");
return "";
}
}

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 args = process.argv;
let duration = 5000;
let interval = 100;
let length = 30;
let color = hexToAnsi("#ffffff");
args.forEach((arg, index) => {
switch (arg) {
case "--duration":
duration = args[index + 1];
break;
case "--interval":
interval = parseInt(args[index + 1]);
break;
case "--length":
length = parseInt(args[index + 1]);
break;
case "--color":
color = hexToAnsi(args[index + 1]);
break;
default:
break;
}
});

let progress = 0;
const steps = Math.ceil(duration / interval);
const timer = setInterval(() => {
progress++;
const percent = Math.min((progress / steps) * 100, 100);
const filledLength = Math.round((length * percent) / 100);
if (progress > steps) {
const bar = color + "█".repeat(filledLength);
console.log("\nDone");
clearInterval(timer);
}

const bar =
color + "█".repeat(filledLength) + " ".repeat(length - filledLength);

process.stdout.write(`\r[${bar}] ${percent.toFixed(1)}%`);
}, interval);
};
progress();
22 changes: 22 additions & 0 deletions src/cp/execCommand.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
import { Worker, } from "worker_threads";
import {spawn} from "child_process"

function setArrayInWorker() {
const worker = new Worker(`
const
`);
}

const execCommand = () => {
// Write your code here
// Take command from CLI argument
// Spawn child process
// Pipe child stdout/stderr to parent stdout/stderr
// Pass environment variables
// Exit with same code as child
const command=process.argv[2];
if (!command) {
console.error("No command provided. Usage: node execCommand.js \"ls -la\"");
process.exit(1);
}
const child=spawn(command,{
shell:true,
env: process.env
})
child.stdout.pipe(process.stdout)
child.stdin.pipe(process.stdin)
child.on('close', (code)=>process.exit(code))

};

execCommand();
29 changes: 29 additions & 0 deletions src/fs/findByExt.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
import fs from "fs/promises";
import path from "path";

const findByExt = async () => {
// Write your code here
// Recursively find all files with specific extension
// Parse --ext CLI argument (default: .txt)

const root = process.cwd();
const filesArray = [];
async function scanDir(ext, dir) {
const files = await fs.readdir(dir);
for (let file of files) {
const fullPath = path.join(dir, file);
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) await scanDir(ext, fullPath);
else {
if (path.extname(file).replace(".", "") === ext) {
filesArray.push(path.relative(root, fullPath));
}
}
}
}

try {
const index = process.argv.indexOf("--ext");
if (index < 0) throw new Error("Not found");
const ext = process.argv[index + 1];
await scanDir(ext, root);
console.log(filesArray);
} catch (e) {
console.error("Error\n", "FS operation failed", "\n\n");
}
};

await findByExt();
37 changes: 37 additions & 0 deletions src/fs/merge.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,45 @@
import fs from "fs/promises";
import path from "path";

const merge = async () => {
// Write your code here
// Default: read all .txt files from workspace/parts in alphabetical order
// Optional: support --files filename1,filename2,... to merge specific files in provided order
// Concatenate content and write to workspace/merged.txt

const root = path.join(process.cwd(), "part");
let textFiles = [];
async function readDirectory(pathDir) {
const files = await fs.readdir(pathDir);
for (const file of files) {
const fullPath = path.join(pathDir, file);
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) {
await readDirectory(fullPath);
} else {
if (path.extname(fullPath) === ".txt") {
textFiles.push(fullPath);
}
}
}
}
try {
await readDirectory(root);
if (textFiles.length === 0) {
throw new Error();
}
textFiles.sort((file1, file2) => {
return path.basename(file1).localeCompare(path.basename(file2));
});
let result = "";
for (const file of textFiles) {
const content = await fs.readFile(file);
result += content + "\n";
}
await fs.writeFile(path.join(process.cwd(), "merged.txt"), result);
} catch {
console.error("Error:\n", "FS operation failed", "\n");
}
};

await merge();
25 changes: 25 additions & 0 deletions src/fs/restore.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import fs from "fs/promises";
import path from "path";

const restore = async () => {
// Write your code here
// Read snapshot.json
// Treat snapshot.rootPath as metadata only
// Recreate directory/file structure in workspace_restored
const root = process.cwd();
const rootPath = path.join(root, "restore");

try {
const data = await fs.readFile("./src/fs/snapshot.json");
const files = JSON.parse(data).entries;
await fs.mkdir(rootPath, { recursive: true });

for (const file of files) {
if (file.type === "directory") {
await fs.mkdir(path.join(rootPath, file.path));
}
}

for (const file of files) {
if (file.type === "file") {
await fs.writeFile(path.join(rootPath, file.path), file.content);
}
}
} catch (e) {
console.error("Error\n", "FS operation failed", "\n");
}
};

await restore();
44 changes: 39 additions & 5 deletions src/fs/snapshot.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,43 @@
import fs from "fs"
import path from "path"


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
let entries=[]
const rootPath=process.cwd();

function readDirectory(pathDirectory){
const files=fs.readdirSync(pathDirectory);
for(let file of files){
const fullPath=path.join(pathDirectory, file);
const stat=fs.statSync(fullPath);
if(stat.isFile()){
const content=fs.readFileSync(fullPath,{encoding:"base64"});
entries.push({
path:path.relative(rootPath, fullPath),
type:'file',
size:stat.size,
content
})
}else{
entries.push({
path:path.relative(rootPath, fullPath),
type:"directory"})
readDirectory(fullPath);
}
}
}
try{
readDirectory(rootPath)
const data={
rootPath,
entries
}
fs.writeFileSync("./src/fs/snapshot.json",JSON.stringify(data, "",2))
}catch(e){
console.error("Error\n","FS operation failed",'\n')
}

};

await snapshot();
Empty file added src/hash/file1.txt
Empty file.
Empty file added src/hash/file2.txt
Empty file.
44 changes: 42 additions & 2 deletions src/hash/verify.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,48 @@
import fs from "fs/promises";
import fs2 from "fs";
import crypto from "crypto";
import path from "path";

const verify = async () => {
// Write your code here
// Read checksums.json
// Calculate SHA256 hash using Streams API
// Print result: filename — OK/FAIL
};

await verify();
function calculateHash(filePath) {
return new Promise((resolve, reject) => {
if (!fs2.existsSync(filePath)) {
resolve({ file: filePath, error: "File does not exist" });
return;
}
const hash = crypto.createHash("sha256");
const stream = fs2.createReadStream(filePath);
stream.on("data", (data) => hash.update(data));
stream.on("end", () => {
const result = hash.digest("hex");
resolve({ file: filePath, hash: result });
});
stream.on("error", (err) => reject(err));
});
}

try {
const content = await fs.readFile("src/hash/checksums.json", "utf-8");
const files = JSON.parse(content);
for (const file in files) {
const fullPath = path.join(process.cwd(), "src/hash", file);
const result = await calculateHash(fullPath);
if (result.error) {
console.log(`${file} — ${result.error}`);
} else {
const expectedHash = files[file];
console.log(
`${file} — ${result.hash === expectedHash ? "OK" : "FAIL"}`,
);
}
}
} catch (e) {
console.error("FS operation failed");
}
};
verify();
Loading