From b3bd80d2d34e8d73cdb9d2254faf71bdb5fe36fb Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 00:56:42 +0300 Subject: [PATCH 1/9] feat: add constants --- src/common/consts.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/common/consts.js diff --git a/src/common/consts.js b/src/common/consts.js new file mode 100644 index 0000000000..088e37844f --- /dev/null +++ b/src/common/consts.js @@ -0,0 +1,3 @@ +export const createFileText = 'I am fresh and young'; + +export const fsErrorTest = 'FS operation failed'; \ No newline at end of file From 772eca6101febf14e1337f9cf64c10ac5350f4f6 Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 01:36:08 +0300 Subject: [PATCH 2/9] feat: add fs solutions --- src/common/utils.js | 10 ++++++++++ src/fs/copy.js | 19 ++++++++++++++++++- src/fs/create.js | 12 +++++++++++- src/fs/delete.js | 17 ++++++++++++++++- src/fs/list.js | 18 +++++++++++++++++- src/fs/read.js | 21 ++++++++++++++++++++- src/fs/rename.js | 24 +++++++++++++++++++++++- 7 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 src/common/utils.js diff --git a/src/common/utils.js b/src/common/utils.js new file mode 100644 index 0000000000..681c14a822 --- /dev/null +++ b/src/common/utils.js @@ -0,0 +1,10 @@ +import path from "path"; +import { fileURLToPath } from "url"; + +export const getPath = (metaUrl, relativePath) => { + return path.join(path.dirname(fileURLToPath(metaUrl)), relativePath); +}; + +export const getFilePath = metaUrl => fileURLToPath(metaUrl); + +export const getDirPath = metaUrl => path.dirname(fileURLToPath(metaUrl)); diff --git a/src/fs/copy.js b/src/fs/copy.js index e226075b4c..73752b0b39 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,5 +1,22 @@ +import { mkdir, access, constants, cp } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const copy = async () => { - // Write your code here + try { + const inDirPath = getPath(import.meta.url, "./files"); + const outDirPath = getPath(import.meta.url, "./files_copy"); + + await access(inDirPath, constants.R_OK); + await mkdir(outDirPath, { recursive: false }); + await cp(inDirPath, outDirPath, { + recursive: true, + force: false, + errorOnExist: true, + }); + } catch (error) { + throw new Error(fsErrorTest); + } }; await copy(); diff --git a/src/fs/create.js b/src/fs/create.js index 6ede285599..895f47ab50 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,5 +1,15 @@ +import { writeFile } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { createFileText, fsErrorTest } from "../common/consts.js"; + const create = async () => { - // Write your code here + const filename = getPath(import.meta.url, "./files/fresh.txt"); + + try { + await writeFile(filename, createFileText, { flag: "wx" }); + } catch (err) { + throw new Error(fsErrorTest); + } }; await create(); diff --git a/src/fs/delete.js b/src/fs/delete.js index a70b13766c..c1585048a3 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,5 +1,20 @@ +import { unlink, stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const remove = async () => { - // Write your code here + try { + const deleteFilePath = getPath(import.meta.url, "./files/fileToRemove.txt"); + const isInputFile = await stat(deleteFilePath).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + await unlink(deleteFilePath); + } catch (error) { + throw new Error(fsErrorTest); + } }; await remove(); diff --git a/src/fs/list.js b/src/fs/list.js index 0c0fa21f7e..f3816c5926 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,5 +1,21 @@ +import { readdir } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const list = async () => { - // Write your code here + try { + const sourceFolderPath = getPath(import.meta.url, "./files"); + const dirents = await readdir(sourceFolderPath, { withFileTypes: true }); + const fileNames = dirents.filter(x => x.isFile()).map(x => x.name); + + console.log("\x1b[36m%s\x1b[0m", "Files:\n"); + for (const fileName of fileNames) { + console.log("\x1b[33m%s\x1b[0m", fileName); + } + console.log("\x1b[0m"); + } catch (error) { + throw new Error(fsErrorTest); + } }; await list(); diff --git a/src/fs/read.js b/src/fs/read.js index e3938be563..7beb7c72ef 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,5 +1,24 @@ +import { readFile, stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const read = async () => { - // Write your code here + try { + const sourceFilePath = getPath(import.meta.url, "./files/fileToRead.txt"); + const isInputFile = await stat(sourceFilePath).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + const fileContent = await readFile(sourceFilePath); + + console.log("\x1b[36m%s\x1b[0m", "File content:\n"); + console.log("\x1b[33m%s\x1b[0m", fileContent); + console.log("\x1b[0m"); + } catch (error) { + throw new Error(fsErrorTest); + } }; await read(); diff --git a/src/fs/rename.js b/src/fs/rename.js index b1d65b0c86..502c9675b6 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,5 +1,27 @@ +import { rename as fsRename, access, constants, stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const rename = async () => { - // Write your code here + try { + let isOutputFileExists = false; + const wrongFilePath = getPath(import.meta.url, "./files/wrongFilename.txt"); + const rightFilePath = getPath(import.meta.url, "./files/properFilename.md"); + const isInputFile = await stat(wrongFilePath).then(x => x.isFile()); + + try { + await access(rightFilePath, constants.F_OK); + isOutputFileExists = true; + } catch (error) {} + + if (isOutputFileExists || !isInputFile) { + throw new Error(fsErrorTest); + } + + await fsRename(wrongFilePath, rightFilePath); + } catch (error) { + throw new Error(fsErrorTest); + } }; await rename(); From e73f3441315bbee34519d934810b42c336544a79 Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 01:46:31 +0300 Subject: [PATCH 3/9] feat: add cli solutions --- src/cli/args.js | 20 +++++++++++++++++++- src/cli/env.js | 12 +++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/cli/args.js b/src/cli/args.js index 9e3622f791..70bc066bee 100644 --- a/src/cli/args.js +++ b/src/cli/args.js @@ -1,5 +1,23 @@ const parseArgs = () => { - // Write your code here + const args = process.argv.slice(2); + const resultsPairs = []; + + for (let i = 0; i < args.length; i++) { + if (args[i].startsWith("--")) { + resultsPairs.push( + `\x1b[32m${args[i].slice(2)}\x1b[0m is \x1b[33m${args[i + 1]}\x1b[0m` + ); + i++; + } + } + if (resultsPairs.length) { + console.log( + `\x1b[36m Command cli arg${ + resultsPairs.length > 1 ? "s are" : " is" + }: \x1b[0m \n` + ); + console.log(resultsPairs.join(", ")); + } }; parseArgs(); diff --git a/src/cli/env.js b/src/cli/env.js index e3616dc8e7..b40d9fd214 100644 --- a/src/cli/env.js +++ b/src/cli/env.js @@ -1,5 +1,15 @@ const parseEnv = () => { - // Write your code here + const prefix = "RSS_"; + + const props = Object.entries(process.env).filter(x => + x[0].startsWith(prefix) + ); + + console.log("\x1b[36m env variables start with \x1b[0m", `"${prefix}":\n`); + const result = props + .map(prop => `\x1b[32m${prop[0]}\x1b[0m=\x1b[33m${prop[1]}\x1b[0m`) + .join("; "); + console.log(result); }; parseEnv(); From ce8f9b938e4bc7a6c901e8464dbb3a14944c2417 Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 02:00:49 +0300 Subject: [PATCH 4/9] feat: add module solution --- src/modules/cjsToEsm.cjs | 34 ---------------------------------- src/modules/esm.mjs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 34 deletions(-) delete mode 100644 src/modules/cjsToEsm.cjs create mode 100644 src/modules/esm.mjs diff --git a/src/modules/cjsToEsm.cjs b/src/modules/cjsToEsm.cjs deleted file mode 100644 index 089bd2db13..0000000000 --- a/src/modules/cjsToEsm.cjs +++ /dev/null @@ -1,34 +0,0 @@ -const path = require('node:path'); -const { release, version } = require('node:os'); -const { createServer: createServerHttp } = require('node:http'); - -require('./files/c.cjs'); - -const random = Math.random(); - -const unknownObject = random > 0.5 ? require('./files/a.json') : require('./files/b.json'); - -console.log(`Release ${release()}`); -console.log(`Version ${version()}`); -console.log(`Path segment separator is "${path.sep}"`); - -console.log(`Path to current file is ${__filename}`); -console.log(`Path to current directory is ${__dirname}`); - -const myServer = createServerHttp((_, res) => { - res.end('Request accepted'); -}); - -const PORT = 3000; - -console.log(unknownObject); - -myServer.listen(PORT, () => { - console.log(`Server is listening on port ${PORT}`); - console.log('To terminate it, use Ctrl+C combination'); -}); - -module.exports = { - unknownObject, - myServer, -}; diff --git a/src/modules/esm.mjs b/src/modules/esm.mjs new file mode 100644 index 0000000000..1d9271e7aa --- /dev/null +++ b/src/modules/esm.mjs @@ -0,0 +1,35 @@ +import path from "path"; +import { release, version } from "os"; +import { createServer as createServerHttp } from "http"; +import { getFilePath, getDirPath } from "../common/utils.js"; +import { createRequire } from "node:module"; +import "./files/c.cjs"; + +const random = Math.random(); +const filepath = random > 0.5 ? "./files/a.json" : "./files/b.json"; + +const newRequire = createRequire(import.meta.url); + +let unknownObject = newRequire(filepath); + +console.log(`Release ${release()}`); +console.log(`Version ${version()}`); +console.log(`Path segment separator is "${path.sep}"`); + +console.log(`Path to current file is ${getFilePath(import.meta.url)}`); +console.log(`Path to current directory is ${getDirPath(import.meta.url)}`); + +const myServer = createServerHttp((_, res) => { + res.end("Request accepted"); +}); + +const PORT = 3000; + +console.log(unknownObject); + +myServer.listen(PORT, () => { + console.log(`Server is listening on port ${PORT}`); + console.log("To terminate it, use Ctrl+C combination"); +}); + +export { myServer, unknownObject }; From 01d8406297bbb68691fba49da3c8eb3991163d9d Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 02:06:30 +0300 Subject: [PATCH 5/9] feat: add hash solution --- src/hash/calcHash.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/hash/calcHash.js b/src/hash/calcHash.js index e37c17ed62..83c81a4ea1 100644 --- a/src/hash/calcHash.js +++ b/src/hash/calcHash.js @@ -1,5 +1,37 @@ +import { createReadStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { createHash } from "node:crypto"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const calculateHash = async () => { - // Write your code here + const filename = getPath( + import.meta.url, + "./files/fileToCalculateHashFor.txt" + ); + try { + const isInputFile = await stat(filename).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + const hash = createHash("sha256"); + createReadStream(filename) + .pipe(hash) + .on("finish", () => { + console.log( + `Hash of file \x1b[36m ${filename} \x1b[0m is \n \x1b[33m${hash.digest( + "hex" + )}\x1b[0m` + ); + }) + .on("error", () => { + throw new Error(fsErrorTest); + }); + } catch (error) { + throw new Error(fsErrorTest); + } }; await calculateHash(); From 8b54e69d3a903de6015288305e063c40fcee207c Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 02:18:37 +0300 Subject: [PATCH 6/9] feat: add stream solutions --- src/streams/read.js | 29 ++++++++++++++++++++++++++++- src/streams/transform.js | 21 ++++++++++++++++++++- src/streams/write.js | 22 +++++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/streams/read.js b/src/streams/read.js index e3938be563..c1913d9f75 100644 --- a/src/streams/read.js +++ b/src/streams/read.js @@ -1,5 +1,32 @@ +import { createReadStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const read = async () => { - // Write your code here + const filename = getPath(import.meta.url, "./files/fileToRead.txt"); + try { + const isInputFile = await stat(filename).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + createReadStream(filename) + .on("end", () => { + console.log(""); + }) + .on("error", () => { + throw new Error(fsErrorTest); + }) + .pipe(process.stdout) + .on("error", () => { + throw new Error(fsErrorTest); + }); + + } catch (error) { + throw new Error(fsErrorTest); + } }; await read(); diff --git a/src/streams/transform.js b/src/streams/transform.js index 9e6c15fe84..f5efd8bca1 100644 --- a/src/streams/transform.js +++ b/src/streams/transform.js @@ -1,5 +1,24 @@ +import { Transform, pipeline } from "stream"; + +class MyTransform extends Transform { + _transform(chunk, encoding, callback) { + try { + const resultString = + chunk.toString("utf-8").split("").reverse().join("") + "\n"; + callback(null, resultString); + } catch (err) { + callback(err); + } + } +} + const transform = async () => { - // Write your code here + const myTransformStream = new MyTransform(); + pipeline(process.stdin, myTransformStream, process.stdout, err => { + if (err) { + throw new Error(fsErrorTest); + } + }); }; await transform(); diff --git a/src/streams/write.js b/src/streams/write.js index 84aa11e7cb..8949b34295 100644 --- a/src/streams/write.js +++ b/src/streams/write.js @@ -1,5 +1,25 @@ +import { createWriteStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const write = async () => { - // Write your code here + const filepath = getPath(import.meta.url, "./files/fileToWrite.txt"); + try { + const isInputFile = await stat(filepath).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + const writeStream = createWriteStream(filepath); + + process.stdin.pipe(writeStream).on("error", () => { + throw new Error(fsErrorTest); + }); + } catch (error) { + throw new Error(fsErrorTest); + } }; await write(); From f21bfc6fe006acb15931975302243490ef4fe1c5 Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 02:24:49 +0300 Subject: [PATCH 7/9] feat: add zlib solutions --- src/zip/compress.js | 29 ++++++++++++++++++++++++++++- src/zip/decompress.js | 29 ++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/zip/compress.js b/src/zip/compress.js index d55209587e..c57ee606bd 100644 --- a/src/zip/compress.js +++ b/src/zip/compress.js @@ -1,5 +1,32 @@ +import { createGzip } from "node:zlib"; +import { pipeline } from "node:stream"; +import { createReadStream, createWriteStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const compress = async () => { - // Write your code here + const inputFileName = getPath(import.meta.url, "./files/fileToCompress.txt"); + const outputFileName = getPath(import.meta.url, "./files/archive.gz"); + try { + const isInputFile = await stat(inputFileName).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + const gzip = createGzip(); + const source = createReadStream(inputFileName); + const destination = createWriteStream(outputFileName); + + pipeline(source, gzip, destination, err => { + if (err) { + throw new Error(fsErrorTest); + } + }); + } catch (error) { + throw new Error(fsErrorTest); + } }; await compress(); diff --git a/src/zip/decompress.js b/src/zip/decompress.js index 8aaf26c8a4..325c842742 100644 --- a/src/zip/decompress.js +++ b/src/zip/decompress.js @@ -1,5 +1,32 @@ +import { createGunzip } from "node:zlib"; +import { pipeline } from "node:stream"; +import { createReadStream, createWriteStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { getPath } from "../common/utils.js"; +import { fsErrorTest } from "../common/consts.js"; + const decompress = async () => { - // Write your code here + const inputFileName = getPath(import.meta.url, "./files/archive.gz"); + const outputFileName = getPath(import.meta.url, "./files/fileToCompress.txt"); + try { + const isInputFile = await stat(inputFileName).then(x => x.isFile()); + + if (!isInputFile) { + throw new Error(fsErrorTest); + } + + const gzip = createGunzip(); + const source = createReadStream(inputFileName); + const destination = createWriteStream(outputFileName); + + pipeline(source, gzip, destination, err => { + if (err) { + throw new Error(fsErrorTest); + } + }); + } catch (error) { + throw new Error(fsErrorTest); + } }; await decompress(); From ed1cc49b3bbdd3719ec4654d8e859e5643767f97 Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 02:36:05 +0300 Subject: [PATCH 8/9] feat: add worker threads solution --- src/wt/main.js | 31 ++++++++++++++++++++++++++++++- src/wt/worker.js | 17 +++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/wt/main.js b/src/wt/main.js index e2ef054d41..937a336c13 100644 --- a/src/wt/main.js +++ b/src/wt/main.js @@ -1,5 +1,34 @@ +import { Worker } from "worker_threads"; +import { cpus } from "os"; +import { getPath } from "../common/utils.js"; + +const workerPromise = (filename, data) => { + return new Promise((resolve, reject) => { + const worker = new Worker(filename, { + workerData: data, + }); + worker.on("message", resolve); + worker.on("error", reject); + worker.on("exit", code => { + if (code !== 0) + reject(new Error(`Worker stopped with exit code ${code}`)); + }); + }); +}; + const performCalculations = async () => { - // Write your code here + const workerFileName = getPath(import.meta.url, "./worker.js"); + const workersResult = await Promise.allSettled( + cpus().map((x, i) => workerPromise(workerFileName, 10 + i)) + ).then(y => + y.map(r => + r.status === "fulfilled" + ? { status: "resolved", data: r.value } + : { status: "error", data: null } + ) + ); + + console.log(workersResult); }; await performCalculations(); diff --git a/src/wt/worker.js b/src/wt/worker.js index 405595394d..dbec677527 100644 --- a/src/wt/worker.js +++ b/src/wt/worker.js @@ -1,8 +1,21 @@ +import { workerData, parentPort } from "worker_threads"; // n should be received from main thread -const nthFibonacci = (n) => n < 2 ? n : nthFibonacci(n - 1) + nthFibonacci(n - 2); +const nthFibonacci = n => + n < 2 ? n : nthFibonacci(n - 1) + nthFibonacci(n - 2); const sendResult = () => { - // This function sends result of nthFibonacci computations to main thread + // uncomment below if you want to check with fallen threads + + /* + if (Math.random() > 0.5) { + throw new Error(); + } else { + parentPort.postMessage(nthFibonacci(workerData)) + } + return; + */ + + parentPort.postMessage(nthFibonacci(workerData)); }; sendResult(); From 2ad79ac2847337dd7a4c82f853bdbf887d9eda91 Mon Sep 17 00:00:00 2001 From: AV-Shell Date: Mon, 27 Oct 2025 02:41:04 +0300 Subject: [PATCH 9/9] feat: add child process solution --- src/cp/cp.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/cp/cp.js b/src/cp/cp.js index 72c6addc9c..d3bbf3a834 100644 --- a/src/cp/cp.js +++ b/src/cp/cp.js @@ -1,6 +1,14 @@ -const spawnChildProcess = async (args) => { - // Write your code here +import { fork } from "child_process"; +import { getPath } from "../common/utils.js"; + +const scriptFilePath = getPath(import.meta.url, "./files/script.js"); + +const spawnChildProcess = async args => { + const child = fork(scriptFilePath, args, { silent: true }); + + process.stdin.pipe(child.stdin); + child.stdout.pipe(process.stdout); }; // Put your arguments in function call to test this functionality -spawnChildProcess( /* [someArgument1, someArgument2, ...] */); +spawnChildProcess(["someArgument1", "someArgument2", "...", 42, 77, 84]);