diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..723ef36f4e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/Readme.md b/Readme.md index 611a505f49..05a64a8fbb 100644 --- a/Readme.md +++ b/Readme.md @@ -1,3 +1,2 @@ # Node.js basics -## !!! Please don't submit Pull Requests to this repository !!! diff --git a/package.json b/package.json index 867fb44337..79e1053463 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,24 @@ "description": "This repository is the part of nodejs-assignments https://github.com/AlreadyBored/nodejs-assignments", "type": "module", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "read": "node src/fs/read.js", + "copy": "node src/fs/copy.js", + "create": "node src/fs/create.js", + "list-files": "node src/fs/list.js", + "delete": "node src/fs/delete.js", + "rename": "node src/fs/rename.js", + "cp": "node src/cp/cp.js", + "args": "node src/cli/args.js --first-name Masha --last-name Marchenko", + "env": "npx cross-env RSS_first_name=Masha RSS_last_name=Marchenko birthyear=2001 node src/cli/env.js", + "calc-hash": "node src/hash/calcHash.js", + "modules": "node src/modules/cjsToEsm.mjs", + "read-stream": "node src/streams/read.js", + "transform-stream": "node src/streams/transform.js", + "write-stream": "node src/streams/write.js", + "wt": "node src/wt/main.js", + "compress": "node src/zip/compress.js", + "decompress": "node src/zip/decompress.js" }, "repository": { "type": "git", diff --git a/src/cli/args.js b/src/cli/args.js index d5d723807d..644262cf50 100644 --- a/src/cli/args.js +++ b/src/cli/args.js @@ -1,3 +1,15 @@ export const parseArgs = () => { - // Write your code here -}; \ No newline at end of file + const userInputArgs = process.argv.slice(2); + const cliArguments = userInputArgs.reduce((acc, arg, index, arr) => { + const value = arr[index + 1]; + if (value && arg.startsWith('--')) { + const transformedArg = arg.slice(2); + const cliArgumentsTransformed = `${transformedArg} is ${value}`; + acc.push(cliArgumentsTransformed); + } return acc; + }, []) + + console.log(cliArguments.join(', ')); +}; + +parseArgs(); \ No newline at end of file diff --git a/src/cli/env.js b/src/cli/env.js index 30fbb5034c..cd8a32faad 100644 --- a/src/cli/env.js +++ b/src/cli/env.js @@ -1,3 +1,9 @@ export const parseEnv = () => { - // Write your code here -}; \ No newline at end of file + const rssVariables = Object.entries(process.env) + .filter(([key, _]) => key.startsWith('RSS_')) + .map(([key, value]) => `${key}=${value}`) + + console.log(rssVariables.join('; ')) +}; + +parseEnv(); \ No newline at end of file diff --git a/src/common.js b/src/common.js new file mode 100644 index 0000000000..52bac9fd8f --- /dev/null +++ b/src/common.js @@ -0,0 +1,8 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; + +export function getDirname(url) { + const __filename = fileURLToPath(url); + + return dirname(__filename); +} \ No newline at end of file diff --git a/src/cp/cp.js b/src/cp/cp.js index b7f4e2c9d8..77ab27a334 100644 --- a/src/cp/cp.js +++ b/src/cp/cp.js @@ -1,3 +1,15 @@ +import child_process from 'child_process'; +import path from "path"; +import {getDirname} from "../common.js"; + export const spawnChildProcess = async (args) => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'script.js'); + + const child = child_process.fork(filePath, args) + + process.stdin.pipe(child.stdin); + child.stdout.pipe(process.stdin); +}; + +spawnChildProcess('--silent --all') \ No newline at end of file diff --git a/src/fs/constants.js b/src/fs/constants.js new file mode 100644 index 0000000000..6ecf0f4867 --- /dev/null +++ b/src/fs/constants.js @@ -0,0 +1 @@ +export const DEFAULT_ERROR_MESSAGE = 'FS operation failed.'; diff --git a/src/fs/copy.js b/src/fs/copy.js index f134d98ac4..144c9e7666 100644 --- a/src/fs/copy.js +++ b/src/fs/copy.js @@ -1,3 +1,22 @@ +import fs from 'fs/promises'; +import path from 'path'; +import {DEFAULT_ERROR_MESSAGE} from "./constants.js"; +import { getDirname } from '../common.js' + + export const copy = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const srcPath = path.join(__dirname, 'files'); + const destPath = path.join(__dirname, 'files_copy'); + + try { + await fs.mkdir(destPath); + const srcFiles = await fs.readdir(srcPath); + await Promise.all(srcFiles.map(file => fs.copyFile(path.join(srcPath, file), path.join(destPath, file)))) + .then(() => 'The files were copied to a new folder') + } catch { + throw new Error(DEFAULT_ERROR_MESSAGE); + } +}; + +copy(); \ No newline at end of file diff --git a/src/fs/create.js b/src/fs/create.js index 16a74c9a23..ed17c0e6c7 100644 --- a/src/fs/create.js +++ b/src/fs/create.js @@ -1,3 +1,17 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { DEFAULT_ERROR_MESSAGE } from "./constants.js"; +import { getDirname } from "../common.js"; + + export const create = async () => { - // Write your code here -}; \ No newline at end of file + const filePath = path.join(getDirname(import.meta.url), 'files', 'fresh.txt'); + const content = 'I am fresh and young'; + try { + await fs.writeFile(filePath, content, {flag: 'wx'}).then(() => console.log('"fresh.txt" was created')) + } catch { + throw new Error(DEFAULT_ERROR_MESSAGE) + } +}; + +create(); \ No newline at end of file diff --git a/src/fs/delete.js b/src/fs/delete.js index 56381a8582..a371fe4067 100644 --- a/src/fs/delete.js +++ b/src/fs/delete.js @@ -1,3 +1,19 @@ +import path from "path"; +import fs from 'fs'; +import {DEFAULT_ERROR_MESSAGE} from "./constants.js"; +import {getDirname} from "../common.js"; + export const remove = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'fileToRemove.txt'); + + fs.rm(filePath, (err) => { + if (err) { + throw new Error(DEFAULT_ERROR_MESSAGE); + } else { + console.log('The file was deleted'); + } + }) +}; + +remove(); \ No newline at end of file diff --git a/src/fs/files/hello.txt b/src/fs/files/hello.txt index 4e65f7775f..ba7d34ee9f 100644 --- a/src/fs/files/hello.txt +++ b/src/fs/files/hello.txt @@ -1 +1 @@ -Hello Node.js \ No newline at end of file +Hello node.js \ No newline at end of file diff --git a/src/fs/list.js b/src/fs/list.js index 4d4d95cb02..e681b7035a 100644 --- a/src/fs/list.js +++ b/src/fs/list.js @@ -1,3 +1,19 @@ +import path from "path"; +import fs from "fs"; +import {DEFAULT_ERROR_MESSAGE} from "./constants.js"; +import {getDirname} from "../common.js"; + export const list = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filesPath = path.join(__dirname, 'files'); + + if (!fs.existsSync(filesPath)) { + throw new Error(DEFAULT_ERROR_MESSAGE); + } + + fs.readdir(filesPath, (_, files) => { + console.log(files) + }) +} + +list(); \ No newline at end of file diff --git a/src/fs/read.js b/src/fs/read.js index 97de16448b..36d9976783 100644 --- a/src/fs/read.js +++ b/src/fs/read.js @@ -1,3 +1,17 @@ +import path from "path"; +import fs from "fs"; +import {DEFAULT_ERROR_MESSAGE} from "./constants.js"; +import {getDirname} from "../common.js"; + export const read = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'fileToRead.txt'); + + if (!fs.existsSync(filePath)) { + throw new Error(DEFAULT_ERROR_MESSAGE); + } + + fs.readFile(filePath, 'utf8', (err, data) => console.log(data)) +}; + +read(); \ No newline at end of file diff --git a/src/fs/rename.js b/src/fs/rename.js index 15ac96f569..b6ac917f56 100644 --- a/src/fs/rename.js +++ b/src/fs/rename.js @@ -1,3 +1,25 @@ +import path from "path"; +import fs from "fs"; +import {DEFAULT_ERROR_MESSAGE} from "./constants.js"; +import {getDirname} from "../common.js"; + export const rename = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const wrongNamedFilePath = path.join(__dirname, 'files', 'wrongFilename.txt'); + const newFilePath = path.join(__dirname, 'files', 'properFilename.md') + + if (!fs.existsSync(wrongNamedFilePath) || fs.existsSync(newFilePath)) { + throw new Error(DEFAULT_ERROR_MESSAGE); + } + + fs.rename(wrongNamedFilePath, newFilePath, (err) => { + if (err) { + throw new Error(DEFAULT_ERROR_MESSAGE); + } else { + console.log('The file was renamed') + } + }); +}; + +rename(); + diff --git a/src/hash/calcHash.js b/src/hash/calcHash.js index c98ad7c74e..35532f787a 100644 --- a/src/hash/calcHash.js +++ b/src/hash/calcHash.js @@ -1,3 +1,17 @@ +import crypto from 'crypto'; +import fs from 'fs'; +import path, {dirname} from "path"; +import {fileURLToPath} from "url"; + export const calculateHash = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = dirname(fileURLToPath(import.meta.url)); + const filePath = path.join(__dirname, 'files', 'fileToCalculateHashFor.txt'); + const readable = fs.createReadStream(filePath); + const hash = crypto.createHash('sha256'); + + return new Promise(resolve => { + readable.on('data', data => hash.update(data)).on('end', () => resolve(hash.digest('hex'))) + }) +}; + +console.log(await calculateHash()); \ No newline at end of file diff --git a/src/modules/cjsToEsm.cjs b/src/modules/cjsToEsm.cjs deleted file mode 100644 index ec022f2334..0000000000 --- a/src/modules/cjsToEsm.cjs +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -const { release, version } = require('os'); -const { createServer: createServerHttp } = require('http'); -require('./files/c'); - -const random = Math.random(); - -let unknownObject; - -if (random > 0.5) { - unknownObject = require('./files/a.json'); -} else { - unknownObject = 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 createMyServer = createServerHttp((_, res) => { - res.end('Request accepted'); -}); - -module.exports = { - unknownObject, - createMyServer, -}; - diff --git a/src/modules/cjsToEsm.mjs b/src/modules/cjsToEsm.mjs new file mode 100644 index 0000000000..0f4234a87c --- /dev/null +++ b/src/modules/cjsToEsm.mjs @@ -0,0 +1,31 @@ +import { release, version } from 'os'; +import { createServer as createServerHttp } from 'http'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import './files/c.js'; +import { getDirname } from "../common.js"; + +const random = Math.random(); +const __dirname = getDirname(import.meta.url); +const __filename = fileURLToPath(import.meta.url); + +const { default: unknownObject } = random > 0.5 ? + await import('./files/a.json', { assert: { type: "json" } }) : + import('./files/b.json', { assert: { type: "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 createMyServer = createServerHttp((_, res) => { + res.end('Request accepted'); +}); + +export { + unknownObject, + createMyServer, +}; + diff --git a/src/streams/read.js b/src/streams/read.js index 97de16448b..28a014f9ab 100644 --- a/src/streams/read.js +++ b/src/streams/read.js @@ -1,3 +1,12 @@ +import path from "path"; +import fs from 'fs'; +import {getDirname} from "../common.js"; + export const read = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'fileToRead.txt'); + const readableStream = fs.createReadStream(filePath); + readableStream.pipe(process.stdout); +}; + +read(); \ No newline at end of file diff --git a/src/streams/transform.js b/src/streams/transform.js index 8647b19cb7..4f869e4f54 100644 --- a/src/streams/transform.js +++ b/src/streams/transform.js @@ -1,3 +1,24 @@ +import {pipeline, Transform} from 'stream' + export const transform = async () => { - // Write your code here -}; \ No newline at end of file + const readableFromTerminal = process.stdin; + const writableToTerminal = process.stdout; + const transform = new Transform({ + transform(chunk, _, callback) { + const chunkStringified = chunk.toString().trim(); + const reversedChunk = chunkStringified.split('').reverse().join(''); + + callback(null, reversedChunk + '\n') + } + }) + + pipeline( + readableFromTerminal, + transform, + writableToTerminal, + err => { + if (err) console.log(err); + }); +}; + +transform(); \ No newline at end of file diff --git a/src/streams/write.js b/src/streams/write.js index 5de058e9d0..ef198ac3ea 100644 --- a/src/streams/write.js +++ b/src/streams/write.js @@ -1,3 +1,13 @@ +import fs from 'fs'; +import path from 'path'; +import { getDirname } from "../common.js"; + export const write = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'fileToWrite.txt'); + const readableFromTerminal = process.stdin; + const writableToFile = fs.createWriteStream(filePath); + readableFromTerminal.pipe(writableToFile); +}; + +write(); \ No newline at end of file diff --git a/src/wt/main.js b/src/wt/main.js index bf1a722c5d..c576673f8d 100644 --- a/src/wt/main.js +++ b/src/wt/main.js @@ -1,3 +1,24 @@ +import os from 'os'; +import { Worker } from 'worker_threads'; +import path from "path"; +import { getDirname } from "../common.js"; + export const performCalculations = async () => { - // Write your code here -}; \ No newline at end of file + const numOfCpus = os.cpus().length; + const workers = []; + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'worker.js'); + + for (let i = 0; i <= numOfCpus; i++) { + const workerPromise = new Promise((resolve) => { + const worker = new Worker(filePath, {workerData: 10 + i}); + worker.on('message', message => resolve({ status: 'resolved', data: message })) + worker.on('error', () => resolve({ status: 'error', data: null })) + }) + workers.push(workerPromise) + } + + return await Promise.all(workers); +}; + +console.log(await performCalculations()); \ No newline at end of file diff --git a/src/wt/worker.js b/src/wt/worker.js index cd70ff6e3d..ccf01708ac 100644 --- a/src/wt/worker.js +++ b/src/wt/worker.js @@ -1,6 +1,9 @@ -// n should be received from main thread +import { workerData, parentPort } from 'worker_threads'; + export const nthFibonacci = (n) => n < 2 ? n : nthFibonacci(n - 1) + nthFibonacci(n - 2); export const sendResult = () => { - // This function sends result of nthFibonacci computations to main thread -}; \ No newline at end of file + parentPort.postMessage(nthFibonacci(workerData)); +}; + +sendResult(); diff --git a/src/zip/compress.js b/src/zip/compress.js index cb3b11ce62..e9d6d0669c 100644 --- a/src/zip/compress.js +++ b/src/zip/compress.js @@ -1,3 +1,25 @@ +import zlib from 'zlib'; +import fs from 'fs'; +import {pipeline} from "stream"; +import path from "path"; +import {getDirname} from "../common.js"; + + export const compress = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'fileToCompress.txt'); + const archivePath = path.join(__dirname, 'files', 'archive.gz'); + const zip = zlib.createGzip(); + const readable = fs.createReadStream(filePath); + const writable = fs.createWriteStream(archivePath); + pipeline( + readable, + zip, + writable, + (err) => { + if (err) console.log(err); + } + ); +}; + +compress(); diff --git a/src/zip/decompress.js b/src/zip/decompress.js index b509804edf..9352b9e36e 100644 --- a/src/zip/decompress.js +++ b/src/zip/decompress.js @@ -1,3 +1,20 @@ +import zlib from 'zlib'; +import fs from 'fs'; +import {pipeline} from "stream"; +import path from "path"; +import {getDirname} from "../common.js"; + + export const decompress = async () => { - // Write your code here -}; \ No newline at end of file + const __dirname = getDirname(import.meta.url); + const filePath = path.join(__dirname, 'files', 'fileToCompress.txt'); + const archivePath = path.join(__dirname, 'files', 'archive.gz'); + const unzip = zlib.createUnzip(); + const readable = fs.createReadStream(archivePath); + const writable = fs.createWriteStream(filePath); + pipeline(readable, unzip, writable, (err) => { + if (err) console.log(err) + }); +}; + +decompress() \ No newline at end of file diff --git a/src/zip/files/archive.gz b/src/zip/files/archive.gz new file mode 100644 index 0000000000..229151a5a2 Binary files /dev/null and b/src/zip/files/archive.gz differ