From 50609c255298e4e7ac528ae0e43b6e433f9ff3bd Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Thu, 23 Oct 2025 20:49:10 +0300 Subject: [PATCH 01/15] finished fs --- src/fs/copy.js | 57 ++++++++++++++++++- src/fs/create.js | 25 +++++++- src/fs/delete.js | 22 ++++++- .../{wrongFilename.txt => wrongFileName.md} | 0 src/fs/list.js | 25 +++++++- src/fs/read.js | 19 ++++++- src/fs/rename.js | 34 ++++++++++- 7 files changed, 171 insertions(+), 11 deletions(-) rename src/fs/files/{wrongFilename.txt => wrongFileName.md} (100%) diff --git a/src/fs/copy.js b/src/fs/copy.js index e226075b4c..14ca681f15 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,5 +1,58 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = path.dirname(_filename); + const copy = async () => { - // Write your code here + const srcToFiles = path.join(_dirname, 'files'); + const destFilesCopy = path.join(_dirname, 'files_copy'); + + try { + // Проверка существования исходной папки + await fs.access(srcToFiles); + + // Проверка, существует ли уже папка назначения + try { + await fs.access(destFilesCopy); + throw new Error('FS operation failed'); + } catch (error) { + // Если ошибка не связана с отсутствием папки, работаем дальше + if (error.message === 'FS operation failed') throw error; + + // Создаем основную папку + await fs.mkdir(destFilesCopy); + + // Рекурсия-функция для копирования + const copyItems = async (currentSrc, currentDestination) => { + const items = await fs.readdir(currentSrc); + + for (const item of items) { + const srcPath = path.join(currentSrc, item); + const destPath = path.join(currentDestination, item); + const stat = await fs.stat(srcPath); + + if (stat.isFile()) { + // Копируем файл + await fs.copyFile(srcPath, destPath); + } else if (stat.isDirectory()) { + // Создаем подпапку и копируем её контент + await fs.mkdir(destPath); + await copyItems(srcPath, destPath); + } + } + }; + + // Стартуем копирование + await copyItems(srcToFiles, destFilesCopy); + } + } catch (error) { + if (error.message !== 'FS operation failed') { + throw new Error('FS operation failed'); + } + throw error; + } }; -await copy(); +await copy(); \ No newline at end of file diff --git a/src/fs/create.js b/src/fs/create.js index 6ede285599..b21ef4be37 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,5 +1,26 @@ +import { promises as fs } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const fileName = fileURLToPath(import.meta.url); +const _dirName = dirname(fileName); + const create = async () => { - // Write your code here -}; + const filePath = join(_dirName, 'files', 'fresh.txt'); + const content = 'I am fresh and young'; + try { + await fs.access(filePath); + + const errorText = 'FS operation failed'; + throw new Error(errorText); + } catch (error) { + if (error.code === 'ENOENT') { + const standard = 'utf8'; + await fs.writeFile(filePath, content, standard); + } else { + throw error; + } + } +}; await create(); diff --git a/src/fs/delete.js b/src/fs/delete.js index a70b13766c..918dfdc4b3 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,5 +1,23 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const fileName = fileURLToPath(import.meta.url); +const dirName = path.dirname(fileName); + const remove = async () => { - // Write your code here + const filePath = path.join(dirName, 'files', 'fileToRemove.txt'); + + try { + // Проверяем существует ли файл + await fs.access(filePath); + + // Удаляем файл + await fs.unlink(filePath); + } catch (error) { + // Если файла нет или произошла к-л ошибка + throw new Error('FS operation failed'); + } }; -await remove(); +await remove(); \ No newline at end of file diff --git a/src/fs/files/wrongFilename.txt b/src/fs/files/wrongFileName.md similarity index 100% rename from src/fs/files/wrongFilename.txt rename to src/fs/files/wrongFileName.md diff --git a/src/fs/list.js b/src/fs/list.js index 0c0fa21f7e..355ae1065a 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,5 +1,26 @@ +import { fileURLToPath } from 'url'; +import fs from 'fs/promises'; +import path from 'path'; + +const _fileName = fileURLToPath(import.meta.url); +const _dirName = path.dirname(_fileName); + const list = async () => { - // Write your code here + const folderPath = path.join(_dirName, 'files'); + + try { + // Проверяем существует ли папка + await fs.access(folderPath); + + // Смотрим содержимое папки + const files = await fs.readdir(folderPath); + + // Массив имен файлов в консоль + console.log(files); + } catch (error) { + // Даем ошибку + throw new Error('FS operation failed'); + } }; -await list(); +await list(); \ No newline at end of file diff --git a/src/fs/read.js b/src/fs/read.js index e3938be563..5af6833e2e 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,5 +1,22 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const _fileName = fileURLToPath(import.meta.url); +const _dirName = path.dirname(_fileName); + const read = async () => { - // Write your code here + const fileToReadName = 'fileToRead.txt'; + const filePath = path.join(_dirName, 'files', fileToReadName); + + try { + await fs.access(filePath); + const standard = 'utf-8'; + const content = await fs.readFile(filePath, standard); + console.log(content); + } catch (error) { + throw new Error('FS operation failed'); + } }; await read(); diff --git a/src/fs/rename.js b/src/fs/rename.js index b1d65b0c86..1e004a5af2 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,5 +1,35 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + const rename = async () => { - // Write your code here + const wrongFilePath = path.join(__dirname, 'files', 'wrongFilename.txt'); + const properFilePath = path.join(__dirname, 'files', 'wrongFileName.md'); + + try { + // Проверяем существование исходного файла + await fs.access(wrongFilePath); + + // Проверяем, не существует ли уже целевой файл + try { + await fs.access(properFilePath); + throw new Error('FS operation failed'); + } catch (error) { + // Если ошибка не связана с отсутствием файла, пробрасываем дальше + if (error.message === 'FS operation failed') throw error; + + // Переименовываем файл + await fs.rename(wrongFilePath, properFilePath); + } + } catch (error) { + if (error.message !== 'FS operation failed') { + throw new Error('FS operation failed'); + } + throw error; + } }; -await rename(); +await rename(); \ No newline at end of file From 9e9ebe134e75841f46b1b48de936204c288ed1ec Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Thu, 23 Oct 2025 21:09:34 +0300 Subject: [PATCH 02/15] finished cli --- src/cli/args.js | 13 +++++++++++-- src/cli/env.js | 9 ++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/cli/args.js b/src/cli/args.js index 9e3622f791..b33aab48c5 100644 --- a/src/cli/args.js +++ b/src/cli/args.js @@ -1,5 +1,14 @@ const parseArgs = () => { - // Write your code here + const args = process.argv.slice(2); + const result = []; + + for (let i = 0; i < args.length; i += 2) { + const propName = args[i].slice(2); // Удалим '--' + const value = args[i + 1]; + result.push(`${propName} is ${value}`); + } + + console.log(result.join(', ')); }; -parseArgs(); +parseArgs(); \ No newline at end of file diff --git a/src/cli/env.js b/src/cli/env.js index e3616dc8e7..ff3fc99596 100644 --- a/src/cli/env.js +++ b/src/cli/env.js @@ -1,5 +1,12 @@ const parseEnv = () => { - // Write your code here + const envV = process.env; + const rssV = []; + for (const key in envV) { + if (key.startsWith('RSS_')) { + rssV.push(`${key}=${envV[key]}`); + } + } + console.log(rssV.join('; ')); }; parseEnv(); From 15d421b17ead24b8e661f771000325db90e8422f Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Thu, 23 Oct 2025 21:20:30 +0300 Subject: [PATCH 03/15] finished modules --- src/modules/esm.mjs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 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..9892e2b6fb --- /dev/null +++ b/src/modules/esm.mjs @@ -0,0 +1,44 @@ +import path from 'node:path'; +import { release, version } from 'node:os'; +import { createServer as createServerHttp } from 'node:http'; +import { fileURLToPath } from 'node:url'; +import { createRequire } from 'node:module'; +import './files/c.cjs'; + +// Создадим функцию для ESM контекста +const require = createRequire(import.meta.url); + +const random = Math.random(); + +// Dynamic imports for conditional JSON loading +const unknownObject = random > 0.5 ? require('./files/a.json') : require('./files/b.json'); + +// Get __filename and __dirname equivalents in ESM +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +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'); +}); + +// Named exports +export { + unknownObject, + myServer, +}; \ No newline at end of file From 9981265096d84fe5bced6e631026a64817a1faa4 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Thu, 23 Oct 2025 21:20:51 +0300 Subject: [PATCH 04/15] finished modules --- src/modules/cjsToEsm.cjs | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/modules/cjsToEsm.cjs 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, -}; From e03b4ff1c581af1381758437911880cc45288f82 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 11:07:51 +0300 Subject: [PATCH 05/15] finished calc Hash refactored esm --- src/hash/calcHash.js | 29 ++++++++++++++++++++++++++++- src/modules/esm.mjs | 24 ++++++++++-------------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/hash/calcHash.js b/src/hash/calcHash.js index e37c17ed62..e0ceb1ed10 100644 --- a/src/hash/calcHash.js +++ b/src/hash/calcHash.js @@ -1,5 +1,32 @@ +import { createHash } from 'crypto'; +import { createReadStream } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + const calculateHash = async () => { - // Write your code here + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + const fileNameToCalculateHashFor = 'fileToCalculateHashFor.txt'; + const filePath = join(_dirname, 'files', fileNameToCalculateHashFor); + + return new Promise((res, rej) => { + const hash = createHash('sha256'); + const stream = createReadStream(filePath); + + stream.on('data', (chunk) => { + hash.update(chunk); + }); + + stream.on('end', () => { + const hexHash = hash.digest('hex'); + console.log(hexHash); + res(hexHash); + }); + + stream.on('error', (error) => { + rej(error); + }); + }); }; await calculateHash(); diff --git a/src/modules/esm.mjs b/src/modules/esm.mjs index 9892e2b6fb..28ebbe1f72 100644 --- a/src/modules/esm.mjs +++ b/src/modules/esm.mjs @@ -2,21 +2,20 @@ import path from 'node:path'; import { release, version } from 'node:os'; import { createServer as createServerHttp } from 'node:http'; import { fileURLToPath } from 'node:url'; -import { createRequire } from 'node:module'; +import { readFileSync } from 'node:fs'; import './files/c.cjs'; -// Создадим функцию для ESM контекста -const require = createRequire(import.meta.url); - -const random = Math.random(); - -// Dynamic imports for conditional JSON loading -const unknownObject = random > 0.5 ? require('./files/a.json') : require('./files/b.json'); - // Get __filename and __dirname equivalents in ESM const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const random = Math.random(); + +// Load JSON files using readFileSync (pure ESM approach) +const unknownObject = random > 0.5 + ? JSON.parse(readFileSync(new URL('./files/a.json', import.meta.url), 'utf-8')) + : JSON.parse(readFileSync(new URL('./files/b.json', import.meta.url), 'utf-8')); + console.log(`Release ${release()}`); console.log(`Version ${version()}`); console.log(`Path segment separator is "${path.sep}"`); @@ -37,8 +36,5 @@ myServer.listen(PORT, () => { console.log('To terminate it, use Ctrl+C combination'); }); -// Named exports -export { - unknownObject, - myServer, -}; \ No newline at end of file +// ESM exports (replaces module.exports) +export { unknownObject, myServer }; \ No newline at end of file From e4c7eba39a3ea275e92f0eac0939cf6b3f74f929 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 11:58:58 +0300 Subject: [PATCH 06/15] finished streams --- src/streams/read.js | 27 +++++++++++++++++++++++-- src/streams/transform.js | 43 +++++++++++++++++++++++++++++++++++++++- src/streams/write.js | 35 +++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/src/streams/read.js b/src/streams/read.js index e3938be563..744edcc459 100644 --- a/src/streams/read.js +++ b/src/streams/read.js @@ -1,5 +1,28 @@ +import { createReadStream } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = dirname(_filename); + const read = async () => { - // Write your code here + const filePath = join(_dirname, 'files', 'fileToRead.txt'); + const readableStream = createReadStream(filePath, { encoding: 'utf-8' }); + + return new Promise((resolve, reject) => { + let content = ''; + + readableStream.on('data', (chunk) => { + content += chunk; + }); + + readableStream.on('end', () => { + console.log(content); + resolve(); + }); + + readableStream.on('error', reject); + }); }; -await read(); +await read(); \ No newline at end of file diff --git a/src/streams/transform.js b/src/streams/transform.js index 9e6c15fe84..f0d26baba1 100644 --- a/src/streams/transform.js +++ b/src/streams/transform.js @@ -1,5 +1,46 @@ +import { Transform } from 'stream'; + const transform = async () => { - // Write your code here + // Создаем Transform Stream для реверсирования текста + const reverseTransform = new Transform({ + transform(chunk, encoding, callback) { + // Преобразуем chunk в строку, реверсируем и добавляем перенос строки + const reversedText = chunk.toString().split('').reverse().join('') + '\n'; + this.push(reversedText); + callback(); + } + }); + + return new Promise((resolve, reject) => { + // Направляем stdin -> transform -> stdout + process.stdin + .pipe(reverseTransform) + .pipe(process.stdout); + + // Обработка завершения + process.stdin.on('end', () => { + console.log('\nTransform completed'); + resolve(); + }); + + // Обработка ошибок + process.stdin.on('error', (error) => { + reject(new Error(`Stdin error: ${error.message}`)); + }); + + reverseTransform.on('error', (error) => { + reject(new Error(`Transform error: ${error.message}`)); + }); + + process.stdout.on('error', (error) => { + reject(new Error(`Stdout error: ${error.message}`)); + }); + }); }; await transform(); + +// Как запустить скрипт и проверить результат +// Запустить +// Ввести в консоли строку для реверса +// Для завершения работы скрипта CTRL-C diff --git a/src/streams/write.js b/src/streams/write.js index 84aa11e7cb..36606b3c30 100644 --- a/src/streams/write.js +++ b/src/streams/write.js @@ -1,5 +1,38 @@ +import { createWriteStream } from 'fs'; +import { pipeline } from 'stream/promises'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + const write = async () => { - // Write your code here + // Получаем текущую директорию файла + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + + // Формируем путь к файлу в папке files + const filePath = join(_dirname, 'files', 'fileToWrite.txt'); + + try { + await pipeline( + process.stdin, + createWriteStream(filePath) + ); + console.log(`Data successfully written to ${filePath}`); + } catch (error) { + console.error('Error:', error.message); + throw error; + } }; await write(); + +/** КАК ЗАПУСКАТЬ СКРИПТ И ПРОВЕРЯТЬ РЕЗУЛЬТАТ + * + * # Ввод с клавиатуры (завершить Ctrl+D или Ctrl+C) + * node write.js + * + * # Передача данных через pipe + * echo "Hello World" | node write.js + * + * # Передача файла + * cat input.txt | node write.js + */ \ No newline at end of file From bee9f7a0b53548a8b94b5f1e23bcfa3bd666a90a Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 16:31:02 +0300 Subject: [PATCH 07/15] finished zip --- src/zip/compress.js | 47 +++++++++++++++++++++++++++++++++++++++++-- src/zip/decompress.js | 26 +++++++++++++++++++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/zip/compress.js b/src/zip/compress.js index d55209587e..5ffc22119c 100644 --- a/src/zip/compress.js +++ b/src/zip/compress.js @@ -1,5 +1,48 @@ +import { createReadStream, createWriteStream } from 'fs'; +import { createGzip } from 'zlib'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + const compress = async () => { - // Write your code here + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + + const sourceFileName = 'fileToCompress.txt'; + const sourceFile = join(_dirname, 'files', sourceFileName); + + const archiveFileName = 'archive.gz'; + const archiveFile = join(_dirname, 'files', archiveFileName); + + return new Promise((resolve, reject) => { + const readStrm = createReadStream(sourceFile); + const writeStrm = createWriteStream(archiveFile); + const gzip = createGzip(); + + let tBytes = 0; + let comprBytes = 0; + + readStrm.on('data', (chunk) => { + tBytes += chunk.length; + }); + + writeStrm.on('data', (chunk) => { + comprBytes += chunk.length; + }); + + readStrm + .pipe(gzip) + .pipe(writeStrm) + .on('finish', () => { + console.log(`Compress finished!`); + console.log(`1st size: ${tBytes} bytes`); + console.log(`After compressing: ${comprBytes} bytes`); + resolve(); + }) + .on('error', (error) => { + console.error('Error:', error.message); + reject(error); + }); + }); }; -await compress(); +await compress(); \ No newline at end of file diff --git a/src/zip/decompress.js b/src/zip/decompress.js index 8aaf26c8a4..f2baba3a62 100644 --- a/src/zip/decompress.js +++ b/src/zip/decompress.js @@ -1,5 +1,29 @@ +import { createReadStream, createWriteStream } from 'fs'; +import { createGunzip } from 'zlib'; +import { pipeline } from 'stream/promises'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + const decompress = async () => { - // Write your code here + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + + const archFileName = 'archive.gz' + const archFile = join(_dirname, 'files', archFileName); + const outFileName = 'fileToCompress.txt'; + const outFile = join(_dirname, 'files', outFileName); + + try { + await pipeline( + createReadStream(archFile), + createGunzip(), + createWriteStream(outFile) + ); + console.log(`Decompressed to ${outFile}`); + } catch (error) { + console.error('Error:', error.message); + throw error; + } }; await decompress(); From ac1846f108497f6b0f4f3c665797edbd297b000d Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 18:35:47 +0300 Subject: [PATCH 08/15] finished cp, workers --- src/cp/cp.js | 32 +++++++++++++++++++++++++++++--- src/wt/main.js | 35 ++++++++++++++++++++++++++++++++++- src/wt/worker.js | 10 +++++++++- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/cp/cp.js b/src/cp/cp.js index 72c6addc9c..43b9c073b6 100644 --- a/src/cp/cp.js +++ b/src/cp/cp.js @@ -1,6 +1,32 @@ +import { spawn } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// ДЛЯ ЦЕЛЕЙ ТЕСТИРОВАНИЯ РАБОТЫ ПРИЛОЖЕНИЯ СРАЗУ ПОСЛЕ СТАРТА ВВЕСТИ ЛЮБУЮ СТРОКУ +// И НАЖАТЬ ЕНТЕР. ЧТОБЫ ВЫЙТИЁ ИЗ ПРОЦЕССА ВВЕСЬТИ CLOSE именно большими буквами + const spawnChildProcess = async (args) => { - // Write your code here + // Путь к script.js в папке files + const scriptPath = join(__dirname, 'files', 'script.js'); + + const childProcess = spawn('node', [scriptPath, ...args], { + stdio: ['pipe', 'pipe', 'inherit'] + }); + + // Связываем stdin и stdout родительского и дочернего процессов + process.stdin.pipe(childProcess.stdin); + childProcess.stdout.pipe(process.stdout); + + // Обработка завершения дочернего процесса + childProcess.on('exit', (code) => { + console.log(`\nChild process exited with code ${code}`); + }); + + return childProcess; }; -// Put your arguments in function call to test this functionality -spawnChildProcess( /* [someArgument1, someArgument2, ...] */); +// Тестируем с аргументами +spawnChildProcess(['argument1', 'argument2', 'argument3', 'argument4']); \ No newline at end of file diff --git a/src/wt/main.js b/src/wt/main.js index e2ef054d41..3fb500016d 100644 --- a/src/wt/main.js +++ b/src/wt/main.js @@ -1,5 +1,38 @@ +import { Worker } from 'worker_threads'; +import os from 'os'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + const performCalculations = async () => { - // Write your code here + const cpuCores = os.cpus().length; + + // Создаем массив промисов для еври worker + const workerPromises = Array.from({ length: cpuCores }, (_, i) => { + return new Promise((resolve) => { + const worker = new Worker(join(__dirname, 'worker.js'), { + workerData: 10 + i + }); + + worker.on('message', (result) => { + resolve({ status: 'resolved', data: result }); + }); + + worker.on('error', () => { + resolve({ status: 'error', data: null }); + }); + + worker.on('exit', (code) => { + if (code !== 0) { + resolve({ status: 'error', data: null }); + } + }); + }); + }); + + const workerResults = await Promise.all(workerPromises); + console.log(workerResults); }; await performCalculations(); diff --git a/src/wt/worker.js b/src/wt/worker.js index 405595394d..f71d761bf0 100644 --- a/src/wt/worker.js +++ b/src/wt/worker.js @@ -1,8 +1,16 @@ +import { parentPort, workerData } from 'worker_threads'; + // n should be received from main thread const nthFibonacci = (n) => n < 2 ? n : nthFibonacci(n - 1) + nthFibonacci(n - 2); const sendResult = () => { - // This function sends result of nthFibonacci computations to main thread + try { + const n = workerData; + const result = nthFibonacci(n); + parentPort.postMessage(result); + } catch (error) { + parentPort.postMessage(null); + } }; sendResult(); From 322a478a1070398ed8b893660639235b4cccfcb3 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:07:40 +0300 Subject: [PATCH 09/15] cli completed --- src/cli/args.js | 11 ++++++++++- src/cli/env.js | 9 ++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cli/args.js b/src/cli/args.js index 9e3622f791..10598842fa 100644 --- a/src/cli/args.js +++ b/src/cli/args.js @@ -1,5 +1,14 @@ const parseArgs = () => { - // Write your code here + const args = process.argv.slice(2); + const result = []; + + for (let i = 0; i < args.length; i += 2) { + const propName = args[i].slice(2); // Удалим '--' + const value = args[i + 1]; + result.push(`${propName} is ${value}`); + } + + console.log(result.join(', ')); }; parseArgs(); diff --git a/src/cli/env.js b/src/cli/env.js index e3616dc8e7..ff3fc99596 100644 --- a/src/cli/env.js +++ b/src/cli/env.js @@ -1,5 +1,12 @@ const parseEnv = () => { - // Write your code here + const envV = process.env; + const rssV = []; + for (const key in envV) { + if (key.startsWith('RSS_')) { + rssV.push(`${key}=${envV[key]}`); + } + } + console.log(rssV.join('; ')); }; parseEnv(); From 679b413891ca7d6a2bd3b32d4988339101788643 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:13:00 +0300 Subject: [PATCH 10/15] fs completed --- src/fs/copy.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++- src/fs/create.js | 25 +++++++++++++++++++-- src/fs/delete.js | 22 +++++++++++++++++-- src/fs/list.js | 25 +++++++++++++++++++-- src/fs/read.js | 19 +++++++++++++++- src/fs/rename.js | 32 ++++++++++++++++++++++++++- 6 files changed, 171 insertions(+), 9 deletions(-) diff --git a/src/fs/copy.js b/src/fs/copy.js index e226075b4c..aba8ea2cfa 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,5 +1,60 @@ const copy = async () => { - // Write your code here + import fs from 'fs/promises'; + import path from 'path'; + import { fileURLToPath } from 'url'; + + const _filename = fileURLToPath(import.meta.url); + const _dirname = path.dirname(_filename); + + const copy = async () => { + const srcToFiles = path.join(_dirname, 'files'); + const destFilesCopy = path.join(_dirname, 'files_copy'); + + try { + // Проверка существования исходной папки + await fs.access(srcToFiles); + + // Проверка, существует ли уже папка назначения + try { + await fs.access(destFilesCopy); + throw new Error('FS operation failed'); + } catch (error) { + // Если ошибка не связана с отсутствием папки, работаем дальше + if (error.message === 'FS operation failed') throw error; + + // Создаем основную папку + await fs.mkdir(destFilesCopy); + + // Рекурсия-функция для копирования + const copyItems = async (currentSrc, currentDestination) => { + const items = await fs.readdir(currentSrc); + + for (const item of items) { + const srcPath = path.join(currentSrc, item); + const destPath = path.join(currentDestination, item); + const stat = await fs.stat(srcPath); + + if (stat.isFile()) { + // Копируем файл + await fs.copyFile(srcPath, destPath); + } else if (stat.isDirectory()) { + // Создаем подпапку и копируем её контент + await fs.mkdir(destPath); + await copyItems(srcPath, destPath); + } + } + }; + + // Стартуем копирование + await copyItems(srcToFiles, destFilesCopy); + } + } catch (error) { + if (error.message !== 'FS operation failed') { + throw new Error('FS operation failed'); + } + throw error; + } + } }; await copy(); diff --git a/src/fs/create.js b/src/fs/create.js index 6ede285599..b21ef4be37 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,5 +1,26 @@ +import { promises as fs } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const fileName = fileURLToPath(import.meta.url); +const _dirName = dirname(fileName); + const create = async () => { - // Write your code here -}; + const filePath = join(_dirName, 'files', 'fresh.txt'); + const content = 'I am fresh and young'; + try { + await fs.access(filePath); + + const errorText = 'FS operation failed'; + throw new Error(errorText); + } catch (error) { + if (error.code === 'ENOENT') { + const standard = 'utf8'; + await fs.writeFile(filePath, content, standard); + } else { + throw error; + } + } +}; await create(); diff --git a/src/fs/delete.js b/src/fs/delete.js index a70b13766c..918dfdc4b3 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,5 +1,23 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const fileName = fileURLToPath(import.meta.url); +const dirName = path.dirname(fileName); + const remove = async () => { - // Write your code here + const filePath = path.join(dirName, 'files', 'fileToRemove.txt'); + + try { + // Проверяем существует ли файл + await fs.access(filePath); + + // Удаляем файл + await fs.unlink(filePath); + } catch (error) { + // Если файла нет или произошла к-л ошибка + throw new Error('FS operation failed'); + } }; -await remove(); +await remove(); \ No newline at end of file diff --git a/src/fs/list.js b/src/fs/list.js index 0c0fa21f7e..355ae1065a 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,5 +1,26 @@ +import { fileURLToPath } from 'url'; +import fs from 'fs/promises'; +import path from 'path'; + +const _fileName = fileURLToPath(import.meta.url); +const _dirName = path.dirname(_fileName); + const list = async () => { - // Write your code here + const folderPath = path.join(_dirName, 'files'); + + try { + // Проверяем существует ли папка + await fs.access(folderPath); + + // Смотрим содержимое папки + const files = await fs.readdir(folderPath); + + // Массив имен файлов в консоль + console.log(files); + } catch (error) { + // Даем ошибку + throw new Error('FS operation failed'); + } }; -await list(); +await list(); \ No newline at end of file diff --git a/src/fs/read.js b/src/fs/read.js index e3938be563..5af6833e2e 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,5 +1,22 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const _fileName = fileURLToPath(import.meta.url); +const _dirName = path.dirname(_fileName); + const read = async () => { - // Write your code here + const fileToReadName = 'fileToRead.txt'; + const filePath = path.join(_dirName, 'files', fileToReadName); + + try { + await fs.access(filePath); + const standard = 'utf-8'; + const content = await fs.readFile(filePath, standard); + console.log(content); + } catch (error) { + throw new Error('FS operation failed'); + } }; await read(); diff --git a/src/fs/rename.js b/src/fs/rename.js index b1d65b0c86..52551778db 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,5 +1,35 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + const rename = async () => { - // Write your code here + const wrongFilePath = path.join(__dirname, 'files', 'wrongFilename.txt'); + const properFilePath = path.join(__dirname, 'files', 'wrongFileName.md'); + + try { + // Проверяем существование исходного файла + await fs.access(wrongFilePath); + + // Проверяем, не существует ли уже целевой файл + try { + await fs.access(properFilePath); + throw new Error('FS operation failed'); + } catch (error) { + // Если ошибка не связана с отсутствием файла, пробрасываем дальше + if (error.message === 'FS operation failed') throw error; + + // Переименовываем файл + await fs.rename(wrongFilePath, properFilePath); + } + } catch (error) { + if (error.message !== 'FS operation failed') { + throw new Error('FS operation failed'); + } + throw error; + } }; await rename(); From eec64dbaf88fb2b88f15c46b2ed0665069387f95 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:14:24 +0300 Subject: [PATCH 11/15] hash completed --- src/hash/calcHash.js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/hash/calcHash.js b/src/hash/calcHash.js index e37c17ed62..c69541575b 100644 --- a/src/hash/calcHash.js +++ b/src/hash/calcHash.js @@ -1,5 +1,32 @@ +import { createHash } from 'crypto'; +import { createReadStream } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + const calculateHash = async () => { - // Write your code here + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + const fileNameToCalculateHashFor = 'fileToCalculateHashFor.txt'; + const filePath = join(_dirname, 'files', fileNameToCalculateHashFor); + + return new Promise((res, rej) => { + const hash = createHash('sha256'); + const stream = createReadStream(filePath); + + stream.on('data', (chunk) => { + hash.update(chunk); + }); + + stream.on('end', () => { + const hexHash = hash.digest('hex'); + console.log(hexHash); + res(hexHash); + }); + + stream.on('error', (error) => { + rej(error); + }); + }); }; -await calculateHash(); +await calculateHash(); \ No newline at end of file From c63d64cd5044e22d168d1ce65ce250bbf6f9b8e4 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:18:23 +0300 Subject: [PATCH 12/15] modules completed --- src/modules/cjsToEsm.cjs | 34 ---------------------------------- src/modules/esm.mjs | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 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..2aa5bb5f9c --- /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'; +import { readFileSync } from 'node:fs'; +import './files/c.cjs'; + +// Get __filename and __dirname equivalents in ESM +const _filename = fileURLToPath(import.meta.url); +const _dirname = path.dirname(_filename); + +const random = Math.random(); + +// Load using readFileSync +const unknownObject = random > 0.5 + ? JSON.parse(readFileSync(new URL('./files/a.json', import.meta.url), 'utf-8')) + : JSON.parse(readFileSync(new URL('./files/b.json', import.meta.url), 'utf-8')); + +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'); +}); + +// ESM exports (replaces module.exports) +export { unknownObject, myServer }; \ No newline at end of file From e6ce7377ce46c077901d6fdfe4cea192f45b040d Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:20:06 +0300 Subject: [PATCH 13/15] streams completed --- src/streams/read.js | 27 ++++++++++++++++++++++-- src/streams/transform.js | 44 +++++++++++++++++++++++++++++++++++++++- src/streams/write.js | 35 +++++++++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/src/streams/read.js b/src/streams/read.js index e3938be563..744edcc459 100644 --- a/src/streams/read.js +++ b/src/streams/read.js @@ -1,5 +1,28 @@ +import { createReadStream } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = dirname(_filename); + const read = async () => { - // Write your code here + const filePath = join(_dirname, 'files', 'fileToRead.txt'); + const readableStream = createReadStream(filePath, { encoding: 'utf-8' }); + + return new Promise((resolve, reject) => { + let content = ''; + + readableStream.on('data', (chunk) => { + content += chunk; + }); + + readableStream.on('end', () => { + console.log(content); + resolve(); + }); + + readableStream.on('error', reject); + }); }; -await read(); +await read(); \ No newline at end of file diff --git a/src/streams/transform.js b/src/streams/transform.js index 9e6c15fe84..51722c0a16 100644 --- a/src/streams/transform.js +++ b/src/streams/transform.js @@ -1,5 +1,47 @@ +import { Transform } from 'stream'; + const transform = async () => { - // Write your code here + // Создаем Transform Stream для реверсирования текста + const reverseTransform = new Transform({ + transform(chunk, encoding, callback) { + // Преобразуем chunk в строку, реверсируем и добавляем перенос строки + const reversedText = chunk.toString().split('').reverse().join('') + '\n'; + this.push(reversedText); + callback(); + } + }); + + return new Promise((resolve, reject) => { + // Направляем stdin -> transform -> stdout + process.stdin + .pipe(reverseTransform) + .pipe(process.stdout); + + // Обработка завершения + process.stdin.on('end', () => { + console.log('\nTransform completed'); + resolve(); + }); + + // Обработка ошибок + process.stdin.on('error', (error) => { + reject(new Error(`Stdin error: ${error.message}`)); + }); + + reverseTransform.on('error', (error) => { + reject(new Error(`Transform error: ${error.message}`)); + }); + + process.stdout.on('error', (error) => { + reject(new Error(`Stdout error: ${error.message}`)); + }); + }); }; await transform(); + +// Как запустить скрипт и проверить результат +// Запустить +// Ввести в консоли строку для реверса +// Для завершения работы скрипта CTRL-C + diff --git a/src/streams/write.js b/src/streams/write.js index 84aa11e7cb..36606b3c30 100644 --- a/src/streams/write.js +++ b/src/streams/write.js @@ -1,5 +1,38 @@ +import { createWriteStream } from 'fs'; +import { pipeline } from 'stream/promises'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + const write = async () => { - // Write your code here + // Получаем текущую директорию файла + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + + // Формируем путь к файлу в папке files + const filePath = join(_dirname, 'files', 'fileToWrite.txt'); + + try { + await pipeline( + process.stdin, + createWriteStream(filePath) + ); + console.log(`Data successfully written to ${filePath}`); + } catch (error) { + console.error('Error:', error.message); + throw error; + } }; await write(); + +/** КАК ЗАПУСКАТЬ СКРИПТ И ПРОВЕРЯТЬ РЕЗУЛЬТАТ + * + * # Ввод с клавиатуры (завершить Ctrl+D или Ctrl+C) + * node write.js + * + * # Передача данных через pipe + * echo "Hello World" | node write.js + * + * # Передача файла + * cat input.txt | node write.js + */ \ No newline at end of file From 02aeba8d8249ef401a51d8680ca8f1ed40f504f7 Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:21:08 +0300 Subject: [PATCH 14/15] wt completed --- src/wt/main.js | 35 ++++++++++++++++++++++++++++++++++- src/wt/worker.js | 10 +++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/wt/main.js b/src/wt/main.js index e2ef054d41..3fb500016d 100644 --- a/src/wt/main.js +++ b/src/wt/main.js @@ -1,5 +1,38 @@ +import { Worker } from 'worker_threads'; +import os from 'os'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + const performCalculations = async () => { - // Write your code here + const cpuCores = os.cpus().length; + + // Создаем массив промисов для еври worker + const workerPromises = Array.from({ length: cpuCores }, (_, i) => { + return new Promise((resolve) => { + const worker = new Worker(join(__dirname, 'worker.js'), { + workerData: 10 + i + }); + + worker.on('message', (result) => { + resolve({ status: 'resolved', data: result }); + }); + + worker.on('error', () => { + resolve({ status: 'error', data: null }); + }); + + worker.on('exit', (code) => { + if (code !== 0) { + resolve({ status: 'error', data: null }); + } + }); + }); + }); + + const workerResults = await Promise.all(workerPromises); + console.log(workerResults); }; await performCalculations(); diff --git a/src/wt/worker.js b/src/wt/worker.js index 405595394d..f71d761bf0 100644 --- a/src/wt/worker.js +++ b/src/wt/worker.js @@ -1,8 +1,16 @@ +import { parentPort, workerData } from 'worker_threads'; + // n should be received from main thread const nthFibonacci = (n) => n < 2 ? n : nthFibonacci(n - 1) + nthFibonacci(n - 2); const sendResult = () => { - // This function sends result of nthFibonacci computations to main thread + try { + const n = workerData; + const result = nthFibonacci(n); + parentPort.postMessage(result); + } catch (error) { + parentPort.postMessage(null); + } }; sendResult(); From 2820c63563c0b3b6bafe6ba11b0ac220545d4cfd Mon Sep 17 00:00:00 2001 From: Mikhail Matsuev Date: Fri, 24 Oct 2025 19:22:19 +0300 Subject: [PATCH 15/15] zip completed --- src/zip/compress.js | 45 ++++++++++++++++++++++++++++++++++++++++++- src/zip/decompress.js | 26 ++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/zip/compress.js b/src/zip/compress.js index d55209587e..831bef1574 100644 --- a/src/zip/compress.js +++ b/src/zip/compress.js @@ -1,5 +1,48 @@ +import { createReadStream, createWriteStream } from 'fs'; +import { createGzip } from 'zlib'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + const compress = async () => { - // Write your code here + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + + const sourceFileName = 'fileToCompress.txt'; + const sourceFile = join(_dirname, 'files', sourceFileName); + + const archiveFileName = 'archive.gz'; + const archiveFile = join(_dirname, 'files', archiveFileName); + + return new Promise((resolve, reject) => { + const readStrm = createReadStream(sourceFile); + const writeStrm = createWriteStream(archiveFile); + const gzip = createGzip(); + + let tBytes = 0; + let comprBytes = 0; + + readStrm.on('data', (chunk) => { + tBytes += chunk.length; + }); + + writeStrm.on('data', (chunk) => { + comprBytes += chunk.length; + }); + + readStrm + .pipe(gzip) + .pipe(writeStrm) + .on('finish', () => { + console.log(`Compress finished!`); + console.log(`1st size: ${tBytes} bytes`); + console.log(`After compressing: ${comprBytes} bytes`); + resolve(); + }) + .on('error', (error) => { + console.error('Error:', error.message); + reject(error); + }); + }); }; await compress(); diff --git a/src/zip/decompress.js b/src/zip/decompress.js index 8aaf26c8a4..f2baba3a62 100644 --- a/src/zip/decompress.js +++ b/src/zip/decompress.js @@ -1,5 +1,29 @@ +import { createReadStream, createWriteStream } from 'fs'; +import { createGunzip } from 'zlib'; +import { pipeline } from 'stream/promises'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + const decompress = async () => { - // Write your code here + const _filename = fileURLToPath(import.meta.url); + const _dirname = dirname(_filename); + + const archFileName = 'archive.gz' + const archFile = join(_dirname, 'files', archFileName); + const outFileName = 'fileToCompress.txt'; + const outFile = join(_dirname, 'files', outFileName); + + try { + await pipeline( + createReadStream(archFile), + createGunzip(), + createWriteStream(outFile) + ); + console.log(`Decompressed to ${outFile}`); + } catch (error) { + console.error('Error:', error.message); + throw error; + } }; await decompress();