From f85456040588957f3b7c5d328cb13935c8ff3a7b Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sat, 25 Oct 2025 19:57:45 +0300 Subject: [PATCH 1/8] feat: add implementation of fs functions --- src/fs/copy.js | 26 +++++++++++++++++++++++++- src/fs/create.js | 18 ++++++++++++++++-- src/fs/delete.js | 11 ++++++++++- src/fs/list.js | 19 ++++++++++++++++++- src/fs/read.js | 17 ++++++++++++++++- src/fs/rename.js | 23 ++++++++++++++++++++++- 6 files changed, 107 insertions(+), 7 deletions(-) diff --git a/src/fs/copy.js b/src/fs/copy.js index e226075b4c..0069444d6e 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,5 +1,29 @@ +import fs from 'node:fs/promises'; + const copy = async () => { - // Write your code here + const sourcePath = 'files'; + const destinationPath = 'files_copy'; + + try { + await fs.access(sourcePath); + } catch (err) { + if (err.code === 'ENOENT') { + throw new Error('FS operation failed'); + } else { + throw err; + } + } + + try { + await fs.access(destinationPath); + throw new Error('FS operation failed'); + } catch (err) { + if (err.code === 'ENOENT') { + await fs.cp(sourcePath, destinationPath, { recursive: true }); + } else { + throw err; + } + } }; await copy(); diff --git a/src/fs/create.js b/src/fs/create.js index 6ede285599..aff222c4a5 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,5 +1,19 @@ +import fs from 'node:fs/promises'; + const create = async () => { - // Write your code here + const filePath = 'files/fresh.txt'; + const content = 'I am fresh and young!'; + + try { + await fs.access(filePath); + throw new Error('FS operation failed'); + } catch (err) { + if (err.code === 'ENOENT') { + await fs.writeFile(filePath, content); + } else { + throw err; + } + } }; -await create(); +await create(); \ No newline at end of file diff --git a/src/fs/delete.js b/src/fs/delete.js index a70b13766c..bf901bfd32 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,5 +1,14 @@ +import fs from 'node:fs/promises'; + const remove = async () => { - // Write your code here + const fileToRemovePath = 'files/fileToRemove.txt'; + + try { + await fs.access(fileToRemovePath); + await fs.unlink(fileToRemovePath); + } catch (err) { + throw new Error('FS operation failed'); + } }; await remove(); diff --git a/src/fs/list.js b/src/fs/list.js index 0c0fa21f7e..028542d36d 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,5 +1,22 @@ +import fs from 'node:fs/promises'; + const list = async () => { - // Write your code here + const folderPath = 'files'; + + try { + await fs.access(folderPath); + } catch (err) { + throw new Error('FS operation failed'); + } + + try { + const files = await fs.readdir(folderPath); + for (const file of files) { + console.log(file); + } + } catch (err) { + throw err; + } }; await list(); diff --git a/src/fs/read.js b/src/fs/read.js index e3938be563..4f6581e3ec 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,5 +1,20 @@ +import fs from 'node:fs/promises'; + const read = async () => { - // Write your code here + const fileToReadPath = 'files/fileToRead.txt'; + + try { + await fs.access(fileToReadPath); + } catch (err) { + throw new Error('FS operation failed'); + } + + try { + const content = await fs.readFile(fileToReadPath, 'utf8'); + console.log(content); + } catch (err) { + throw err; + } }; await read(); diff --git a/src/fs/rename.js b/src/fs/rename.js index b1d65b0c86..2033c15d22 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,5 +1,26 @@ +import fs from 'node:fs/promises'; + const rename = async () => { - // Write your code here + const sourceFile = 'files/wrongFilename.txt'; + const destinationFile = 'files/properFilename.md'; + + try { + await fs.access(sourceFile); + } catch (err) { + throw new Error('FS operation failed'); + } + + try { + await fs.access(destinationFile); + throw new Error('FS operation failed'); + } catch (err) { + if (err.code === 'ENOENT') { + await fs.rename(sourceFile, destinationFile); + } else { + throw err; + } + } + }; await rename(); From 3f133c8df9cae7a8011aece8b35a07bd00fc7b50 Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sat, 25 Oct 2025 21:39:06 +0300 Subject: [PATCH 2/8] feat: add implementation of cli functions --- .gitignore | 1 + src/cli/args.js | 9 ++++++++- src/cli/env.js | 9 ++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..496ee2ca6a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/src/cli/args.js b/src/cli/args.js index 9e3622f791..db48910b2e 100644 --- a/src/cli/args.js +++ b/src/cli/args.js @@ -1,5 +1,12 @@ const parseArgs = () => { - // Write your code here + const argsArr = process.argv.slice(2) + const parsedArgs = argsArr.reduce((acc, item, index) => { + if(item.startsWith('--')) { + return [...acc, `${item.slice(2)} is ${argsArr[index + 1]}`] + } + return acc; + }, []).join(', ') + console.log(parsedArgs) }; parseArgs(); diff --git a/src/cli/env.js b/src/cli/env.js index e3616dc8e7..22eaea4008 100644 --- a/src/cli/env.js +++ b/src/cli/env.js @@ -1,5 +1,12 @@ const parseEnv = () => { - // Write your code here + const parsedArr = Object.keys(process.env).reduce((acc, item) => { + if(item.startsWith('RSS_')) { + return [...acc, `${item}=${process.env[item]}`] + } + return acc; + },[]).join('; ') + + console.log(parsedArr) }; parseEnv(); From 11d3e0f0b37926f2eadad76ea9419b27ccb318ec Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sat, 25 Oct 2025 22:17:38 +0300 Subject: [PATCH 3/8] feat: rewrite cjs to ecmascript notation --- src/modules/{cjsToEsm.cjs => esm.mjs} | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) rename src/modules/{cjsToEsm.cjs => esm.mjs} (53%) diff --git a/src/modules/cjsToEsm.cjs b/src/modules/esm.mjs similarity index 53% rename from src/modules/cjsToEsm.cjs rename to src/modules/esm.mjs index 089bd2db13..7cd12d1fbc 100644 --- a/src/modules/cjsToEsm.cjs +++ b/src/modules/esm.mjs @@ -1,12 +1,18 @@ -const path = require('node:path'); -const { release, version } = require('node:os'); -const { createServer: createServerHttp } = require('node:http'); +import path from 'node:path' +import { fileURLToPath } from 'node:url'; +import { release, version } from 'node:os' +import { createServer as createServerHttp } from 'node:http' +import a from './files/a.json' with { type: 'json' }; +import b from './files/b.json' with { type: 'json' }; -require('./files/c.cjs'); +import './files/c.cjs'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); const random = Math.random(); -const unknownObject = random > 0.5 ? require('./files/a.json') : require('./files/b.json'); +const unknownObject = random > 0.5 ? a : b; console.log(`Release ${release()}`); console.log(`Version ${version()}`); @@ -28,7 +34,4 @@ myServer.listen(PORT, () => { console.log('To terminate it, use Ctrl+C combination'); }); -module.exports = { - unknownObject, - myServer, -}; +export default { unknownObject, myServer } From 2402d81966b5d0ab41c56e954511a871ae42c0c9 Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sat, 25 Oct 2025 23:00:11 +0300 Subject: [PATCH 4/8] feat: add implementation of hash function, add dir info logic --- src/fs/copy.js | 8 ++++++-- src/fs/create.js | 6 +++++- src/fs/delete.js | 6 +++++- src/fs/list.js | 6 +++++- src/fs/read.js | 6 +++++- src/fs/rename.js | 8 ++++++-- src/hash/calcHash.js | 22 +++++++++++++++++++++- src/utils/getDirInfo.js | 9 +++++++++ 8 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 src/utils/getDirInfo.js diff --git a/src/fs/copy.js b/src/fs/copy.js index 0069444d6e..fa2892ae44 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,8 +1,12 @@ +import path from 'node:path'; import fs from 'node:fs/promises'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); const copy = async () => { - const sourcePath = 'files'; - const destinationPath = 'files_copy'; + const sourcePath = path.join(__dirname, 'files'); + const destinationPath = path.join(__dirname, 'files_copy'); try { await fs.access(sourcePath); diff --git a/src/fs/create.js b/src/fs/create.js index aff222c4a5..f72914ca4e 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,7 +1,11 @@ +import path from 'node:path'; import fs from 'node:fs/promises'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); const create = async () => { - const filePath = 'files/fresh.txt'; + const filePath = path.join(__dirname, 'files', 'fresh.txt'); const content = 'I am fresh and young!'; try { diff --git a/src/fs/delete.js b/src/fs/delete.js index bf901bfd32..fcac1e3cb4 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,7 +1,11 @@ +import path from 'node:path'; import fs from 'node:fs/promises'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); const remove = async () => { - const fileToRemovePath = 'files/fileToRemove.txt'; + const fileToRemovePath = path.join(__dirname, 'files', 'fileToRemove.txt'); try { await fs.access(fileToRemovePath); diff --git a/src/fs/list.js b/src/fs/list.js index 028542d36d..1487d3b36e 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,7 +1,11 @@ +import path from 'node:path'; import fs from 'node:fs/promises'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); const list = async () => { - const folderPath = 'files'; + const folderPath = path.join(__dirname, 'files'); try { await fs.access(folderPath); diff --git a/src/fs/read.js b/src/fs/read.js index 4f6581e3ec..cd010961ec 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,7 +1,11 @@ +import path from 'node:path'; import fs from 'node:fs/promises'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); const read = async () => { - const fileToReadPath = 'files/fileToRead.txt'; + const fileToReadPath = path.join(__dirname, 'files', 'fileToRead.txt'); try { await fs.access(fileToReadPath); diff --git a/src/fs/rename.js b/src/fs/rename.js index 2033c15d22..d3709fb424 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,8 +1,12 @@ +import path from 'node:path'; import fs from 'node:fs/promises'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); const rename = async () => { - const sourceFile = 'files/wrongFilename.txt'; - const destinationFile = 'files/properFilename.md'; + const sourceFile = path.join(__dirname, 'files', 'wrongFilename.txt'); + const destinationFile = path.join(__dirname, 'files', 'properFilename.md'); try { await fs.access(sourceFile); diff --git a/src/hash/calcHash.js b/src/hash/calcHash.js index e37c17ed62..b25fbd7894 100644 --- a/src/hash/calcHash.js +++ b/src/hash/calcHash.js @@ -1,5 +1,25 @@ +import crypto from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); + const calculateHash = async () => { - // Write your code here + const filePath = path.join(__dirname, 'files', 'fileToCalculateHashFor.txt'); + + return new Promise((resolve, reject) => { + const hash = crypto.createHash('sha256'); + const stream = fs.createReadStream(filePath); + + stream.on('data', (chunk) => hash.update(chunk)); + stream.on('end', () => { + const finalHash = hash.digest('hex'); + console.log(finalHash); + resolve(finalHash); + }); + stream.on('error', (err) => reject(err)); + }); }; await calculateHash(); diff --git a/src/utils/getDirInfo.js b/src/utils/getDirInfo.js new file mode 100644 index 0000000000..1576e3f5cb --- /dev/null +++ b/src/utils/getDirInfo.js @@ -0,0 +1,9 @@ + +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +export const getDirInfo = (metaUrl) => { + const __filename = fileURLToPath(metaUrl); + const __dirname = path.dirname(__filename); + return { __filename, __dirname }; +}; \ No newline at end of file From e95def307a587a0b10c8d660d2e0ee9dda0b5438 Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sun, 26 Oct 2025 11:27:56 +0300 Subject: [PATCH 5/8] feat: add implementation of streams functions --- src/streams/read.js | 17 ++++++++++++++++- src/streams/transform.js | 12 +++++++++++- src/streams/write.js | 12 +++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/streams/read.js b/src/streams/read.js index e3938be563..ba5f75bfc5 100644 --- a/src/streams/read.js +++ b/src/streams/read.js @@ -1,5 +1,20 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); + const read = async () => { - // Write your code here + const filePath = path.join(__dirname, 'files', 'fileToRead.txt'); + + const stream = fs.createReadStream(filePath); + + stream.on('error', (err) => { + console.error('Error reading file:', err.message); + }); + + stream.pipe(process.stdout); + stream.on('end', () => process.stdout.write('\n')); }; await read(); diff --git a/src/streams/transform.js b/src/streams/transform.js index 9e6c15fe84..3d7cea2235 100644 --- a/src/streams/transform.js +++ b/src/streams/transform.js @@ -1,5 +1,15 @@ +import { Transform } from 'node:stream'; + const transform = async () => { - // Write your code here + const stream = new Transform({ + transform(chunk, _, callback) { + const reversed = [...chunk.toString()].reverse().join(''); + this.push(reversed); + callback(); + }, + }); + + process.stdin.pipe(stream).pipe(process.stdout); }; await transform(); diff --git a/src/streams/write.js b/src/streams/write.js index 84aa11e7cb..ca56f075af 100644 --- a/src/streams/write.js +++ b/src/streams/write.js @@ -1,5 +1,15 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); + const write = async () => { - // Write your code here + const filePath = path.join(__dirname, 'files', 'fileToWrite.txt'); + + const stream = fs.createWriteStream(filePath); + + process.stdin.pipe(stream); }; await write(); From 4d3c0d0b347badf1cb67863122d71c0eb5faeb7f Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sun, 26 Oct 2025 12:27:19 +0300 Subject: [PATCH 6/8] feat: add implementation of zip functions --- src/zip/compress.js | 27 ++++++++++++++++++++++++++- src/zip/decompress.js | 28 ++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/zip/compress.js b/src/zip/compress.js index d55209587e..24acd5d4fd 100644 --- a/src/zip/compress.js +++ b/src/zip/compress.js @@ -1,5 +1,30 @@ +import fs from 'node:fs'; +import fsp from 'node:fs/promises'; +import path from 'node:path'; +import zlib from 'node:zlib'; +import { pipeline } from 'node:stream'; +import { promisify } from 'node:util'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); +const pipe = promisify(pipeline); + const compress = async () => { - // Write your code here + const sourcePath = path.join(__dirname, 'files', 'fileToCompress.txt'); + const destinationPath = path.join(__dirname, 'files', 'archive.gz'); + + const sourceStream = fs.createReadStream(sourcePath); + const gzipStream = zlib.createGzip(); + const destinationStream = fs.createWriteStream(destinationPath); + + try { + await pipe(sourceStream, gzipStream, destinationStream); + + await fsp.unlink(sourcePath); + } catch (error) { + console.error(error); + } }; await compress(); + diff --git a/src/zip/decompress.js b/src/zip/decompress.js index 8aaf26c8a4..a139e507ec 100644 --- a/src/zip/decompress.js +++ b/src/zip/decompress.js @@ -1,5 +1,29 @@ +import fs from 'node:fs'; +import fsp from 'node:fs/promises'; +import path from 'node:path'; +import zlib from 'node:zlib'; +import { pipeline } from 'node:stream'; +import { promisify } from 'node:util'; +import { getDirInfo } from '../utils/getDirInfo.js'; + +const { __dirname } = getDirInfo(import.meta.url); +const pipe = promisify(pipeline); + const decompress = async () => { - // Write your code here + const sourcePath = path.join(__dirname, 'files', 'archive.gz'); + const destinationPath = path.join(__dirname, 'files', 'fileToCompress.txt'); + + const sourceStream = fs.createReadStream(sourcePath); + const gunzipStream = zlib.createGunzip(); + const destinationStream = fs.createWriteStream(destinationPath); + + try { + await pipe(sourceStream, gunzipStream, destinationStream); + + await fsp.unlink(sourcePath); + } catch (error) { + console.error(error); + } }; -await decompress(); +await decompress(); \ No newline at end of file From 6cfeeb60359ce51b3d40783db3dd9ca7eeda024b Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sun, 26 Oct 2025 13:25:16 +0300 Subject: [PATCH 7/8] feat: add implementation of worker threads --- src/wt/main.js | 37 ++++++++++++++++++++++++++++++++++++- src/wt/worker.js | 8 ++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/wt/main.js b/src/wt/main.js index e2ef054d41..d77ba145b3 100644 --- a/src/wt/main.js +++ b/src/wt/main.js @@ -1,5 +1,40 @@ +import os from 'node:os'; +import { Worker } from 'node:worker_threads'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const workerPath = path.join(__dirname, 'worker.js'); + const performCalculations = async () => { - // Write your code here + const cores = os.cpus().length; + const start = 10; + + const tasks = Array.from({ length: cores }, (_, i) => { + const n = start + i; + + return new Promise((resolve) => { + const w = new Worker(workerPath, { workerData: n }); + let settled = false; + + w.once('message', (value) => { + settled = true; + resolve({ status: 'resolved', data: value }); + }); + + w.once('error', () => { + if (!settled) resolve({ status: 'error', data: null }); + }); + + w.once('exit', (code) => { + if (code !== 0 && !settled) resolve({ status: 'error', data: null }); + }); + }); + }); + + const results = await Promise.all(tasks); + console.log(results); }; await performCalculations(); diff --git a/src/wt/worker.js b/src/wt/worker.js index 405595394d..7bc21ea8f6 100644 --- a/src/wt/worker.js +++ b/src/wt/worker.js @@ -1,8 +1,12 @@ -// n should be received from main thread +import { parentPort, workerData } from 'node:worker_threads'; + const nthFibonacci = (n) => n < 2 ? n : nthFibonacci(n - 1) + nthFibonacci(n - 2); const sendResult = () => { - // This function sends result of nthFibonacci computations to main thread + const n = Number(workerData); + if (!Number.isFinite(n)) throw new Error('Invalid input for Fibonacci'); + const result = nthFibonacci(n); + parentPort.postMessage(result); }; sendResult(); From 8a6f139ef41afa21d80b5a2a2b1af4bd1f44dcd0 Mon Sep 17 00:00:00 2001 From: Roman Telyatnik Date: Sun, 26 Oct 2025 14:04:23 +0300 Subject: [PATCH 8/8] feat: add implementation of child process --- src/cp/cp.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/cp/cp.js b/src/cp/cp.js index 72c6addc9c..1ea8547d8d 100644 --- a/src/cp/cp.js +++ b/src/cp/cp.js @@ -1,6 +1,24 @@ -const spawnChildProcess = async (args) => { - // Write your code here +import { spawn } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const spawnChildProcess = (args = []) => { + const scriptPath = path.join(__dirname, 'files', 'script.js'); + + const child = spawn(process.execPath, [scriptPath, ...args], { + stdio: ['pipe', 'pipe', 'inherit'], + }); + + process.stdin.pipe(child.stdin); + child.stdout.pipe(process.stdout); + + child.on('error', (err) => console.error('Child error:', err.message)); + child.on('exit', (code) => console.log(`Child exited with code ${code}`)); }; -// Put your arguments in function call to test this functionality -spawnChildProcess( /* [someArgument1, someArgument2, ...] */); +spawnChildProcess(['test1', 'test2', 'test3', '444']); + +