From 5070d3d1062b7b3bb7be2980eec857732b725014 Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Sun, 26 Oct 2025 15:13:11 +0200 Subject: [PATCH 1/8] feat: add solutions for fs --- src/fs/copy.js | 33 ++++++++++++++++++++++++++++++++- src/fs/create.js | 23 ++++++++++++++++++++++- src/fs/delete.js | 20 +++++++++++++++++++- src/fs/files/fileToRemove.txt | 1 - src/fs/files/wrongFilename.txt | 3 --- src/fs/list.js | 21 ++++++++++++++++++++- src/fs/read.js | 21 ++++++++++++++++++++- src/fs/rename.js | 31 ++++++++++++++++++++++++++++++- 8 files changed, 143 insertions(+), 10 deletions(-) delete mode 100644 src/fs/files/fileToRemove.txt delete mode 100644 src/fs/files/wrongFilename.txt diff --git a/src/fs/copy.js b/src/fs/copy.js index e226075b4c..a26a3498f5 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,5 +1,36 @@ +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + const copy = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const srcDir = path.join(__dirname, 'files'); + const destDir = path.join(__dirname, 'files_copy'); + + try { + // Validate source directory exists + await fs.access(srcDir); + } catch { + throw new Error('FS operation failed'); + } + + // Fail if destination already exists + try { + await fs.access(destDir); + // If access succeeds, destination exists + throw new Error('FS operation failed'); + } catch (err) { + // If error is because it doesn't exist, proceed; else rethrow custom error already thrown + if (err?.message === 'FS operation failed') throw err; // dest exists case above + } + + try { + // Use recursive copy + await fs.cp(srcDir, destDir, { recursive: true }); + } catch { + throw new Error('FS operation failed'); + } }; await copy(); diff --git a/src/fs/create.js b/src/fs/create.js index 6ede285599..2f5574afd0 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,5 +1,26 @@ +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + const create = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const dir = path.join(__dirname, 'files'); + const filePath = path.join(dir, 'fresh.txt'); + const content = 'I am fresh and young inside of the files folder'; + + try { + await fs.access(filePath); + throw new Error('FS operation failed'); + } catch (err) { + if (err?.message === 'FS operation failed') throw err; + } + + try { + await fs.writeFile(filePath, content, 'utf8'); + } catch { + throw new Error('FS operation failed'); + } }; await create(); diff --git a/src/fs/delete.js b/src/fs/delete.js index a70b13766c..6f00f9fb1e 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,5 +1,23 @@ +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + const remove = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const filePath = path.join(__dirname, 'files', 'fileToRemove.txt'); + + try { + await fs.access(filePath); + } catch { + throw new Error('FS operation failed'); + } + + try { + await fs.unlink(filePath); + } catch { + throw new Error('FS operation failed'); + } }; await remove(); diff --git a/src/fs/files/fileToRemove.txt b/src/fs/files/fileToRemove.txt deleted file mode 100644 index 43e64cd45c..0000000000 --- a/src/fs/files/fileToRemove.txt +++ /dev/null @@ -1 +0,0 @@ -How dare you! \ No newline at end of file diff --git a/src/fs/files/wrongFilename.txt b/src/fs/files/wrongFilename.txt deleted file mode 100644 index 38cca5db19..0000000000 --- a/src/fs/files/wrongFilename.txt +++ /dev/null @@ -1,3 +0,0 @@ -# This is a file with a wrong filename - -Hello from **markdown**! \ No newline at end of file diff --git a/src/fs/list.js b/src/fs/list.js index 0c0fa21f7e..4cedbf4332 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,5 +1,24 @@ +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + const list = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const dir = path.join(__dirname, 'files'); + + try { + await fs.access(dir); + } catch { + throw new Error('FS operation failed'); + } + + try { + const entries = await fs.readdir(dir); + console.log(entries); + } catch { + throw new Error('FS operation failed'); + } }; await list(); diff --git a/src/fs/read.js b/src/fs/read.js index e3938be563..6a75ee497e 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,5 +1,24 @@ +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + const read = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const filePath = path.join(__dirname, 'files', 'fileToRead.txt'); + + try { + await fs.access(filePath); + } catch { + throw new Error('FS operation failed'); + } + + try { + const data = await fs.readFile(filePath, 'utf8'); + console.log(data); + } catch { + throw new Error('FS operation failed'); + } }; await read(); diff --git a/src/fs/rename.js b/src/fs/rename.js index b1d65b0c86..472a4ee7ba 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,5 +1,34 @@ +import { promises as fs } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + const rename = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const dir = path.join(__dirname, 'files'); + const oldPath = path.join(dir, 'wrongFilename.txt'); + const newPath = path.join(dir, 'properFilename.md'); + + // Check old exists + try { + await fs.access(oldPath); + } catch { + throw new Error('FS operation failed'); + } + + // Fail if new already exists + try { + await fs.access(newPath); + throw new Error('FS operation failed'); + } catch (err) { + if (err?.message === 'FS operation failed') throw err; + } + + try { + await fs.rename(oldPath, newPath); + } catch { + throw new Error('FS operation failed'); + } }; await rename(); From 49143e1b783b25cc7e9de8009b59b0404687b6eb Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 12:10:17 +0200 Subject: [PATCH 2/8] feat: add solutions for cli --- src/cli/args.js | 15 ++++++++++++++- src/cli/env.js | 7 ++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/cli/args.js b/src/cli/args.js index 9e3622f791..275b8f49ff 100644 --- a/src/cli/args.js +++ b/src/cli/args.js @@ -1,5 +1,18 @@ const parseArgs = () => { - // Write your code here + const args = process.argv.slice(2); + const result = []; + for (let i = 0; i < args.length; i++) { + const token = args[i]; + if (token.startsWith('--')) { + const name = token.slice(2); + const value = args[i + 1]; + if (value && !value.startsWith('--')) { + result.push(`${name} is ${value}`); + i++; // skip value + } + } + } + if (result.length) console.log(result.join(', ')); }; parseArgs(); diff --git a/src/cli/env.js b/src/cli/env.js index e3616dc8e7..332a4a3523 100644 --- a/src/cli/env.js +++ b/src/cli/env.js @@ -1,5 +1,10 @@ const parseEnv = () => { - // Write your code here + const prefix = 'RSS_'; + const result = Object.keys(process.env) + .filter((key) => key.startsWith(prefix)) + .map((key) => `${key}=${process.env[key]}`) + .join('; '); + if (result) console.log(result); }; parseEnv(); From 4620acea3670836b8a9707f0329e93c0e12c528d Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 12:28:31 +0200 Subject: [PATCH 3/8] refactor: rewrite cjsToEsm.cjs to it's equivalent in ECMAScript notation --- src/modules/esm.mjs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/modules/esm.mjs diff --git a/src/modules/esm.mjs b/src/modules/esm.mjs new file mode 100644 index 0000000000..95c3e9ca6b --- /dev/null +++ b/src/modules/esm.mjs @@ -0,0 +1,40 @@ +import path from 'node:path'; +import { release, version } from 'node:os'; +import { createServer as createServerHttp } from 'node:http'; +import { fileURLToPath } from 'node:url'; + +// Load side-effect CommonJS module +import './files/c.cjs'; + +// Emulate __filename and __dirname in ESM +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const random = Math.random(); + +// Conditional JSON module import using top-level await +const unknownObject = ( + await import(random > 0.5 ? './files/a.json' : './files/b.json', { assert: { type: 'json' } }) +).default; + +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'); +}); + +export { unknownObject, myServer }; From cbb8e983018515f78acbcc14bc221d51c179db4e Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 12:34:16 +0200 Subject: [PATCH 4/8] feat: implement function that calculates SHA256 hash --- src/hash/calcHash.js | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/hash/calcHash.js b/src/hash/calcHash.js index e37c17ed62..6da240d466 100644 --- a/src/hash/calcHash.js +++ b/src/hash/calcHash.js @@ -1,5 +1,43 @@ +import { createReadStream } from 'node:fs'; +import { createHash } from 'node:crypto'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +// filepath: c:\Users\Sergeyu\IdeaProjects\node-nodejs-basics\src\hash\calcHash.js const calculateHash = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const filePath = path.join(__dirname, 'files', 'fileToCalculateHashFor.txt'); + + return new Promise((resolve, reject) => { + const hash = createHash('sha256'); + const stream = createReadStream(filePath); + + stream.on('error', (err) => { + console.error('Stream error while reading file:', err.message); + reject(err); + }); + + stream.on('data', (chunk) => { + hash.update(chunk); + }); + + stream.on('end', () => { + try { + const digest = hash.digest('hex'); + console.log(digest); + resolve(digest); + } catch (err) { + console.error('Hash digest error:', err.message); + reject(err); + } + }); + }); }; -await calculateHash(); +try { + await calculateHash(); +} catch (err) { + // Already logged detailed error above; keep outer catch minimal + process.exitCode = 1; +} From d3e804fa35d636ad7d61fe764c02697f030e4440 Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 12:38:18 +0200 Subject: [PATCH 5/8] feat: implement several functions in dedicated files read.js write.js transform.js --- src/streams/read.js | 26 ++++++++++++++++++++++++-- src/streams/transform.js | 24 ++++++++++++++++++++++-- src/streams/write.js | 26 ++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/streams/read.js b/src/streams/read.js index e3938be563..39b1d41f76 100644 --- a/src/streams/read.js +++ b/src/streams/read.js @@ -1,5 +1,27 @@ +import { createReadStream } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { pipeline } from 'node:stream'; + const read = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const filePath = path.join(__dirname, 'files', 'fileToRead.txt'); + + await new Promise((resolve, reject) => { + pipeline(createReadStream(filePath), process.stdout, (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); }; -await read(); +try { + await read(); +} catch (e) { + console.error('Stream read error:', e.message); + process.exitCode = 1; +} diff --git a/src/streams/transform.js b/src/streams/transform.js index 9e6c15fe84..8954e79ec3 100644 --- a/src/streams/transform.js +++ b/src/streams/transform.js @@ -1,5 +1,25 @@ +import { Transform, pipeline } from 'node:stream'; + +const reverseTransform = new Transform({ + transform(chunk, _enc, callback) { + // Reverse the chunk string and push + const reversed = chunk.toString().split('').reverse().join(''); + this.push(reversed); + callback(); + } +}); + const transform = async () => { - // Write your code here + await new Promise((resolve, reject) => { + pipeline(process.stdin, reverseTransform, process.stdout, (err) => { + if (err) reject(err); else resolve(); + }); + }); }; -await transform(); +try { + await transform(); +} catch (e) { + console.error('Stream transform error:', e.message); + process.exitCode = 1; +} diff --git a/src/streams/write.js b/src/streams/write.js index 84aa11e7cb..86dd586d96 100644 --- a/src/streams/write.js +++ b/src/streams/write.js @@ -1,5 +1,27 @@ +import { createWriteStream } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { pipeline } from 'node:stream'; + const write = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const filePath = path.join(__dirname, 'files', 'fileToWrite.txt'); + + await new Promise((resolve, reject) => { + pipeline(process.stdin, createWriteStream(filePath, { flags: 'w' }), (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); }; -await write(); +try { + await write(); +} catch (e) { + console.error('Stream write error:', e.message); + process.exitCode = 1; +} From 13cc4a5469ebc74cf683b4c3b0c0fcd2630757c8 Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 12:48:52 +0200 Subject: [PATCH 6/8] feat: implement several functions in dedicated files that compresses and decompresses using zlib --- src/zip/compress.js | 31 +++++++++++++++++++++++++++++-- src/zip/decompress.js | 31 +++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/zip/compress.js b/src/zip/compress.js index d55209587e..36ef16139d 100644 --- a/src/zip/compress.js +++ b/src/zip/compress.js @@ -1,5 +1,32 @@ +import { createReadStream, createWriteStream } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { pipeline } from 'node:stream'; +import { createGzip } from 'node:zlib'; + const compress = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const sourcePath = path.join(__dirname, 'files', 'fileToCompress.txt'); + const destPath = path.join(__dirname, 'files', 'archive.gz'); + + const gzip = createGzip(); + + await new Promise((resolve, reject) => { + pipeline( + createReadStream(sourcePath), + gzip, + createWriteStream(destPath, { flags: 'w' }), + (err) => { + if (err) reject(err); else resolve(); + } + ); + }); }; -await compress(); +try { + await compress(); +} catch (e) { + console.error('Compression error:', e.message); + process.exitCode = 1; +} diff --git a/src/zip/decompress.js b/src/zip/decompress.js index 8aaf26c8a4..537d55063b 100644 --- a/src/zip/decompress.js +++ b/src/zip/decompress.js @@ -1,5 +1,32 @@ +import { createReadStream, createWriteStream } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { pipeline } from 'node:stream'; +import { createGunzip } from 'node:zlib'; + const decompress = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const sourcePath = path.join(__dirname, 'files', 'archive.gz'); + const destPath = path.join(__dirname, 'files', 'fileToCompress.txt'); + + const gunzip = createGunzip(); + + await new Promise((resolve, reject) => { + pipeline( + createReadStream(sourcePath), + gunzip, + createWriteStream(destPath, { flags: 'w' }), + (err) => { + if (err) reject(err); else resolve(); + } + ); + }); }; -await decompress(); +try { + await decompress(); +} catch (e) { + console.error('Decompression error:', e.message); + process.exitCode = 1; +} From 2db08fcf54c7fbfa9fecc345e9c1173c5de023fb Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 12:55:43 +0200 Subject: [PATCH 7/8] feat: implement several functions with worker threads --- src/wt/main.js | 44 +++++++++++++++++++++++++++++++++++++++++++- src/wt/worker.js | 7 +++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/wt/main.js b/src/wt/main.js index e2ef054d41..86314fbb25 100644 --- a/src/wt/main.js +++ b/src/wt/main.js @@ -1,5 +1,47 @@ +import { cpus } from 'node:os'; +import { Worker } from 'node:worker_threads'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + const performCalculations = async () => { - // Write your code here + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const workerFile = path.join(__dirname, 'worker.js'); + + const coreCount = Math.max(1, cpus().length); + + const promises = []; + for (let i = 0; i < coreCount; i++) { + const n = 10 + i; + promises.push(new Promise((resolve) => { + let settled = false; + const worker = new Worker(workerFile, { workerData: n }); + + worker.on('message', (value) => { + if (!settled) { + settled = true; + resolve({ status: 'resolved', data: value }); + } + }); + + worker.on('error', () => { + if (!settled) { + settled = true; + resolve({ status: 'error', data: null }); + } + }); + + worker.on('exit', (code) => { + if (!settled && code !== 0) { + settled = true; + resolve({ status: 'error', data: null }); + } + }); + })); + } + + const results = await Promise.all(promises); + console.log(results); }; await performCalculations(); diff --git a/src/wt/worker.js b/src/wt/worker.js index 405595394d..66e1ca32b8 100644 --- a/src/wt/worker.js +++ b/src/wt/worker.js @@ -1,8 +1,15 @@ // 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 + if (typeof workerData !== 'number' || Number.isNaN(workerData)) { + throw new Error('Invalid workerData: expected a number'); + } + const result = nthFibonacci(workerData); + parentPort.postMessage(result); }; sendResult(); From c73e249c29e55453c0ddfc86338fd2c7ff608e9e Mon Sep 17 00:00:00 2001 From: Sergeyu Date: Mon, 27 Oct 2025 13:10:21 +0200 Subject: [PATCH 8/8] feat: implement function spawnChildProcess --- src/cp/cp.js | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/cp/cp.js b/src/cp/cp.js index 72c6addc9c..ab5a6eecaf 100644 --- a/src/cp/cp.js +++ b/src/cp/cp.js @@ -1,6 +1,38 @@ -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 = async (args = []) => { + // Resolve path to the script we want to run + const scriptPath = path.join(__dirname, 'files', 'script.js'); + + // Ensure args is an array + const normalizedArgs = Array.isArray(args) ? args.map(String) : []; + + // Spawn a new Node.js process executing the script with provided arguments + const child = spawn(process.execPath, [scriptPath, ...normalizedArgs], { + stdio: ['pipe', 'pipe', 'inherit'], // pipe stdin & stdout, inherit stderr + }); + + // Pipe master stdin to child stdin, and child stdout back to master stdout + process.stdin.pipe(child.stdin); + child.stdout.pipe(process.stdout); + + // Optional: handle errors for visibility + child.on('error', (err) => { + console.error('Child process error:', err); + }); + + // Return a promise that resolves on child exit (so caller can await if desired) + return new Promise((resolve) => { + child.on('exit', (code, signal) => { + resolve({ code, signal }); + }); + }); }; // Put your arguments in function call to test this functionality -spawnChildProcess( /* [someArgument1, someArgument2, ...] */); +await spawnChildProcess(['value1', '1337', '42']);