From 24fabd9fa7c5bf2104146e17d28ec5b8094a87f8 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:05:06 +0300 Subject: [PATCH 01/27] feat: add package.json --- package.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..b011c55 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-file-manager", + "version": "1.0.0", + "description": "RS School Node.js course task 2: File manager", + "main": "src/index.js", + "type": "module", + "scripts": { + "start": "node src/index.js" + }, + "author": "Izy", + "license": "ISC" +} From ff7a8debf2f13af730970b2544886393151d4624 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:05:24 +0300 Subject: [PATCH 02/27] feat: add colored output utils --- src/utils/color-output.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/utils/color-output.js diff --git a/src/utils/color-output.js b/src/utils/color-output.js new file mode 100644 index 0000000..51b82f7 --- /dev/null +++ b/src/utils/color-output.js @@ -0,0 +1,21 @@ +const colors = { + reset: '[0m', + black: '[30m', + red: '[31m', + green: '[32m', + yellow: '[33m', + blue: '[34m', + purple: '[35m', + cyan: '[36m', + white: '[37m', +}; + +export const getColoredText = (color, text) => { + const colorCode = colors[color] ?? colors.reset; + + return `\x1b${colorCode}${text}\x1b${colors.reset}`; +}; + +export const printColoredText = (color, text) => { + console.log(getColoredText(color, text)); +}; From 71d87ce2e01d68f30d40fa4217c3e2ab10203a82 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:05:50 +0300 Subject: [PATCH 03/27] feat: add username related utils --- src/utils/user.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/utils/user.js diff --git a/src/utils/user.js b/src/utils/user.js new file mode 100644 index 0000000..5ec878d --- /dev/null +++ b/src/utils/user.js @@ -0,0 +1,34 @@ +import { getColoredText } from "./color-output.js"; + +const USERNAME_ARG = 'username'; +const DEFAULT_USERNAME = 'Anonymous'; + +const getArgValue = (argName) => { + const args = process.argv.slice(2); + const foundArg = args.find((arg) => arg.startsWith(`--${argName}=`)); + + return foundArg ? foundArg.split('=')[1] : null; +}; + +const getUsername = () => { + const username = getArgValue(USERNAME_ARG); + + return username || DEFAULT_USERNAME; +}; + +export const printWelcomeMessage = () => { + const username = getUsername(); + const coloredUsername = getColoredText('green', username); + + if (username === DEFAULT_USERNAME) { + console.log('No username specified. Using default username: %s.', coloredUsername); + } + + console.log('Welcome to the File Manager, %s!', coloredUsername); +} + +export const printFarewellMessage = () => { + const coloredUsername = getColoredText('green', getUsername()); + + console.log('Thank you for using File Manager, %s, goodbye!', coloredUsername); +} \ No newline at end of file From bc6c8ff153342ae4bd5b034eda2f5fe85e8965f9 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:07:29 +0300 Subject: [PATCH 04/27] feat: add readline interface --- src/index.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/index.js diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..76aae87 --- /dev/null +++ b/src/index.js @@ -0,0 +1,16 @@ +import { createInterface } from 'readline/promises'; +import { printWelcomeMessage, printFarewellMessage } from './utils/user.js'; + +const init = () => { + printWelcomeMessage(); + + const readline = createInterface({ + input: process.stdin, + output: process.stdout, + }); + + readline.on('close', printFarewellMessage); + // readline.on('line', async (input) => await handleInput(input)); +}; + +init(); From 23c61f8420c5c7621147ea9ff6fa7739a009e390 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:30:52 +0300 Subject: [PATCH 05/27] refactor: change colors keys names --- src/utils/color-output.js | 24 ++++++++++++------------ src/utils/user.js | 7 ++++--- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/utils/color-output.js b/src/utils/color-output.js index 51b82f7..1456498 100644 --- a/src/utils/color-output.js +++ b/src/utils/color-output.js @@ -1,19 +1,19 @@ -const colors = { - reset: '[0m', - black: '[30m', - red: '[31m', - green: '[32m', - yellow: '[33m', - blue: '[34m', - purple: '[35m', - cyan: '[36m', - white: '[37m', +const COLORS = { + RESET: '[0m', + BLACK: '[30m', + RED: '[31m', + GREEN: '[32m', + YELLOW: '[33m', + BLUE: '[34m', + PURPLE: '[35m', + CYAN: '[36m', + WHITE: '[37m', }; export const getColoredText = (color, text) => { - const colorCode = colors[color] ?? colors.reset; + const colorCode = COLORS[color] ?? COLORS.RESET; - return `\x1b${colorCode}${text}\x1b${colors.reset}`; + return `\x1b${colorCode}${text}\x1b${COLORS.RESET}`; }; export const printColoredText = (color, text) => { diff --git a/src/utils/user.js b/src/utils/user.js index 5ec878d..f19a1b4 100644 --- a/src/utils/user.js +++ b/src/utils/user.js @@ -1,3 +1,4 @@ +import { EOL } from 'os'; import { getColoredText } from "./color-output.js"; const USERNAME_ARG = 'username'; @@ -18,7 +19,7 @@ const getUsername = () => { export const printWelcomeMessage = () => { const username = getUsername(); - const coloredUsername = getColoredText('green', username); + const coloredUsername = getColoredText('GREEN', username); if (username === DEFAULT_USERNAME) { console.log('No username specified. Using default username: %s.', coloredUsername); @@ -28,7 +29,7 @@ export const printWelcomeMessage = () => { } export const printFarewellMessage = () => { - const coloredUsername = getColoredText('green', getUsername()); + const coloredUsername = getColoredText('GREEN', getUsername()); - console.log('Thank you for using File Manager, %s, goodbye!', coloredUsername); + console.log(`${EOL}Thank you for using File Manager, ${coloredUsername}, goodbye!`); } \ No newline at end of file From 69381a62fa4db5aff4bf483c9cfc3d9ad2a86e37 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:31:36 +0300 Subject: [PATCH 06/27] feat: add directory path utils --- src/utils/directory-path.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/utils/directory-path.js diff --git a/src/utils/directory-path.js b/src/utils/directory-path.js new file mode 100644 index 0000000..3f77ce6 --- /dev/null +++ b/src/utils/directory-path.js @@ -0,0 +1,13 @@ +import { chdir, cwd } from 'process'; +import { homedir, EOL } from 'os'; +import { getColoredText } from "./color-output.js"; + +export const setStartingDir = () => chdir(homedir()); + +export const getCurrentDir = () => cwd(); + +export const printCurrentDirectory = () => { + const coloredPath = getColoredText('YELLOW', getCurrentDir()); + + console.log(`${EOL}You are currently in ${coloredPath}`); +} \ No newline at end of file From 293e6a59b25d4f97788118f36ee69babacaa563f Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:31:56 +0300 Subject: [PATCH 07/27] feat: add command input utils --- src/utils/command-input.js | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/utils/command-input.js diff --git a/src/utils/command-input.js b/src/utils/command-input.js new file mode 100644 index 0000000..64622fa --- /dev/null +++ b/src/utils/command-input.js @@ -0,0 +1,46 @@ +import { EOL } from 'os'; + +export const COMMANDS = { + EXIT: { name: '.exit', argCount: 0 }, + UP: { name: 'up', argCount: 0 }, + CD: { name: 'cd', argCount: 1 }, + LS: { name: 'ls', argCount: 0 }, + CAT: { name: 'cat', argCount: 1 }, + ADD: { name: 'add', argCount: 1 }, + RN: { name: 'rn', argCount: 2 }, + CP: { name: 'cp', argCount: 2 }, + MV: { name: 'mv', argCount: 2 }, + RM: { name: 'rm', argCount: 1 }, + OS: { name: 'os', argCount: 1 }, + HASH: { name: 'hash', argCount: 1 }, + COMPRESS: { name: 'compress', argCount: 2 }, + DECOMPRESS: { name: 'decompress', argCount: 2 }, +}; + +export const trimQuotes = (path) => { + if (!path) { + return ''; + } else { + return path.trim().replace(/^[`"']|[`"']$/g, ''); + } +}; + +export const getArgByNumber = (args, number) => { + let argument = args[argNumber] || ''; + + return trimQuotes(argument); +}; + +export const checkArgCount = (inputCommandName, args) => { + const foundCommand = Object.entries(COMMANDS).find( + ([key, { name }]) => name === inputCommandName + ); + + if (foundCommand) { + const [key, { argCount: expectedArgCount }] = foundCommand; + + if (args.length !== expectedArgCount) { + throw new Error(`Invalid input.${EOL}Command "${inputCommandName}" requires ${expectedArgCount} argument(s).`); + } + } +}; From cebe1dd2c1558ec54e8d63434ab589dfcbb81a78 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:32:58 +0300 Subject: [PATCH 08/27] feat: add input handler --- src/commands/input-handler.js | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/commands/input-handler.js diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js new file mode 100644 index 0000000..e5cab59 --- /dev/null +++ b/src/commands/input-handler.js @@ -0,0 +1,72 @@ +import { checkArgCount, COMMANDS } from "../utils/command-input.js"; +import { printColoredText } from "../utils/color-output.js"; +import { printFarewellMessage } from '../utils/user.js'; +import { printCurrentDirectory } from "../utils/directory-path.js"; + +export const handleInput = async (line) => { + try { + const args = line.match(/([`"']).*?\1|\S+/g) || []; + const command = args.shift(); + + checkArgCount(command, args); + + switch (command) { + case undefined: + break; + case COMMANDS.EXIT.name: + printFarewellMessage(); + process.exit(0); + break; + // case COMMANDS.UP.name: + // up(); + // break; + // case COMMANDS.CD.name: + // cd(args); + // break; + // case COMMANDS.LS.name: + // await ls(); + // break; + // case COMMANDS.CAT.name: + // await cat(args); + // break; + // case COMMANDS.ADD.name: + // await add(args); + // break; + // case COMMANDS.RN.name: + // await rn(args); + // break; + // case COMMANDS.CP.name: + // await cp(args); + // break; + // case COMMANDS.MV.name: + // await mv(args); + // break; + // case COMMANDS.RM.name: + // await rm(args); + // break; + // case COMMANDS.OS.name: + // os(args); + // break; + // case COMMANDS.HASH.name: + // await hash(args); + // break; + // case COMMANDS.COMPRESS.name: + // await compress(args); + // break; + // case COMMANDS.DECOMPRESS.name: + // await decompress(args); + // break; + default: + printColoredText('RED', `Invalid input. Command "${command}" not supported.`); + break; + } + } catch (err) { + if (err.message.startsWith('Invalid input.')) { + printColoredText('RED', err.message); + } else { + printColoredText('RED', `Operation failed.${EOL}${err.message}`); + } + } + + printCurrentDirectory(); +}; From 9b127c08d4cceee483805ee723770e44f466c4cd Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:35:04 +0300 Subject: [PATCH 09/27] feat: add readline prompt and new line handler --- src/index.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 76aae87..efdf272 100644 --- a/src/index.js +++ b/src/index.js @@ -1,16 +1,26 @@ import { createInterface } from 'readline/promises'; import { printWelcomeMessage, printFarewellMessage } from './utils/user.js'; +import { handleInput } from './commands/input-handler.js'; +import { printCurrentDirectory, setStartingDir } from './utils/directory-path.js'; +import { getColoredText } from './utils/color-output.js'; const init = () => { - printWelcomeMessage(); - const readline = createInterface({ input: process.stdin, output: process.stdout, + prompt: getColoredText('BLUE', '> '), }); + printWelcomeMessage(); + setStartingDir(); + printCurrentDirectory(); + readline.prompt(); + readline.on('close', printFarewellMessage); - // readline.on('line', async (input) => await handleInput(input)); + readline.on('line', async (input) => { + await handleInput(input); + readline.prompt(); + }); }; init(); From 7adc7cca9a3e08d4a8d75eca218a21143ad0b634 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:09:09 +0300 Subject: [PATCH 10/27] feat: add up command --- src/commands/input-handler.js | 7 ++++--- src/commands/navigation/up.js | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/commands/navigation/up.js diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index e5cab59..b6e2483 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -2,6 +2,7 @@ import { checkArgCount, COMMANDS } from "../utils/command-input.js"; import { printColoredText } from "../utils/color-output.js"; import { printFarewellMessage } from '../utils/user.js'; import { printCurrentDirectory } from "../utils/directory-path.js"; +import { up } from "./navigation/up.js"; export const handleInput = async (line) => { try { @@ -17,9 +18,9 @@ export const handleInput = async (line) => { printFarewellMessage(); process.exit(0); break; - // case COMMANDS.UP.name: - // up(); - // break; + case COMMANDS.UP.name: + up(); + break; // case COMMANDS.CD.name: // cd(args); // break; diff --git a/src/commands/navigation/up.js b/src/commands/navigation/up.js new file mode 100644 index 0000000..d25e1a6 --- /dev/null +++ b/src/commands/navigation/up.js @@ -0,0 +1,13 @@ +import { resolve, dirname } from 'path'; +import { chdir } from 'process'; +import { platform } from 'os'; +import { getCurrentDir } from '../../utils/directory-path'; + +export const up = () => { + const currentDir = getCurrentDir(); + const parentDir = resolve(currentDir, '..'); + + if (currentDir !== parentDir) { + chdir('..'); + } +}; \ No newline at end of file From b459609fe82dd182c13c0957fdf5f5ffa018104d Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:25:39 +0300 Subject: [PATCH 11/27] fix: del unneeded imports --- src/commands/navigation/up.js | 8 +++----- src/utils/directory-path.js | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/commands/navigation/up.js b/src/commands/navigation/up.js index d25e1a6..cda36b0 100644 --- a/src/commands/navigation/up.js +++ b/src/commands/navigation/up.js @@ -1,13 +1,11 @@ -import { resolve, dirname } from 'path'; -import { chdir } from 'process'; -import { platform } from 'os'; -import { getCurrentDir } from '../../utils/directory-path'; +import { resolve } from 'path'; +import { getCurrentDir } from '../../utils/directory-path.js'; export const up = () => { const currentDir = getCurrentDir(); const parentDir = resolve(currentDir, '..'); if (currentDir !== parentDir) { - chdir('..'); + process.chdir('..'); } }; \ No newline at end of file diff --git a/src/utils/directory-path.js b/src/utils/directory-path.js index 3f77ce6..31ca444 100644 --- a/src/utils/directory-path.js +++ b/src/utils/directory-path.js @@ -1,10 +1,9 @@ -import { chdir, cwd } from 'process'; import { homedir, EOL } from 'os'; import { getColoredText } from "./color-output.js"; -export const setStartingDir = () => chdir(homedir()); +export const setStartingDir = () => process.chdir(homedir()); -export const getCurrentDir = () => cwd(); +export const getCurrentDir = () => process.cwd(); export const printCurrentDirectory = () => { const coloredPath = getColoredText('YELLOW', getCurrentDir()); From 5fdc637340868098a32d0986ee3d662b46761fc8 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 01:09:40 +0300 Subject: [PATCH 12/27] fix: change array index in getArgByNumber --- src/utils/command-input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/command-input.js b/src/utils/command-input.js index 64622fa..9b2f0ba 100644 --- a/src/utils/command-input.js +++ b/src/utils/command-input.js @@ -26,7 +26,7 @@ export const trimQuotes = (path) => { }; export const getArgByNumber = (args, number) => { - let argument = args[argNumber] || ''; + let argument = args[number] || ''; return trimQuotes(argument); }; From a93c2fce69499ddcaa39633f49a9bb1c564d2e33 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 01:10:06 +0300 Subject: [PATCH 13/27] feat: add cd command --- src/commands/input-handler.js | 8 +++++--- src/commands/navigation/cd.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 src/commands/navigation/cd.js diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index b6e2483..d86a66c 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -1,8 +1,10 @@ +import { EOL } from 'os'; import { checkArgCount, COMMANDS } from "../utils/command-input.js"; import { printColoredText } from "../utils/color-output.js"; import { printFarewellMessage } from '../utils/user.js'; import { printCurrentDirectory } from "../utils/directory-path.js"; import { up } from "./navigation/up.js"; +import { cd } from './navigation/cd.js'; export const handleInput = async (line) => { try { @@ -21,9 +23,9 @@ export const handleInput = async (line) => { case COMMANDS.UP.name: up(); break; - // case COMMANDS.CD.name: - // cd(args); - // break; + case COMMANDS.CD.name: + cd(args); + break; // case COMMANDS.LS.name: // await ls(); // break; diff --git a/src/commands/navigation/cd.js b/src/commands/navigation/cd.js new file mode 100644 index 0000000..03cffc6 --- /dev/null +++ b/src/commands/navigation/cd.js @@ -0,0 +1,10 @@ +import { isAbsolute, resolve } from 'path'; +import { getArgByNumber } from "../../utils/command-input.js"; + +export const cd = (args) => { + const path = getArgByNumber(args, 0); + const isWinOsIncompleteRootPath = process.platform === 'win32' && !isAbsolute(path) && path.includes(':'); + const improvedPath = resolve(isWinOsIncompleteRootPath ? '/' : process.cwd(), path); + + process.chdir(improvedPath); +}; \ No newline at end of file From 433909177c96c98df5779880a5c045006858625d Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 01:37:34 +0300 Subject: [PATCH 14/27] feat: add ls command --- src/commands/input-handler.js | 7 ++++--- src/commands/navigation/ls.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/commands/navigation/ls.js diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index d86a66c..2ce9578 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -5,6 +5,7 @@ import { printFarewellMessage } from '../utils/user.js'; import { printCurrentDirectory } from "../utils/directory-path.js"; import { up } from "./navigation/up.js"; import { cd } from './navigation/cd.js'; +import { ls } from './navigation/ls.js'; export const handleInput = async (line) => { try { @@ -26,9 +27,9 @@ export const handleInput = async (line) => { case COMMANDS.CD.name: cd(args); break; - // case COMMANDS.LS.name: - // await ls(); - // break; + case COMMANDS.LS.name: + await ls(); + break; // case COMMANDS.CAT.name: // await cat(args); // break; diff --git a/src/commands/navigation/ls.js b/src/commands/navigation/ls.js new file mode 100644 index 0000000..950ccad --- /dev/null +++ b/src/commands/navigation/ls.js @@ -0,0 +1,20 @@ +import { readdir } from 'fs/promises'; +import { getCurrentDir } from '../../utils/directory-path.js'; + +export const ls = async () => { + const dirents = await readdir(getCurrentDir(), { withFileTypes: true }); + + const getDirentType = (dirent) => + dirent.isFile() ? 'file' + : dirent.isDirectory() ? 'directory' : 'other'; + + const tabularData = dirents + .map((dirent) => ({ + Name: dirent.name, + Type: getDirentType(dirent), + })) + .filter(({ Type }) => Type !== 'other') + .sort((a, b) => a.Type.localeCompare(b.Type) || a.Name.localeCompare(b.Name)); + + console.table(tabularData); +}; \ No newline at end of file From 3fe13c64019759348fefc95cc363d7723140fff3 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:48:20 +0300 Subject: [PATCH 15/27] feat: add cat command --- src/commands/file-system/cat.js | 13 +++++++++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/commands/file-system/cat.js diff --git a/src/commands/file-system/cat.js b/src/commands/file-system/cat.js new file mode 100644 index 0000000..8b44980 --- /dev/null +++ b/src/commands/file-system/cat.js @@ -0,0 +1,13 @@ +import { resolve } from 'path'; +import { createReadStream } from 'fs'; +import { pipeline } from 'stream/promises'; +import { getCurrentDir } from '../../utils/directory-path.js'; +import { getArgByNumber } from "../../utils/command-input.js"; + +export const cat = async (args) => { + const argPath = getArgByNumber(args, 0); + const resolvedPath = resolve(getCurrentDir(), argPath); + const sourceStream = createReadStream(resolvedPath); + + await pipeline(sourceStream, process.stdout, { end: false }); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 2ce9578..8c9f8a7 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -6,6 +6,7 @@ import { printCurrentDirectory } from "../utils/directory-path.js"; import { up } from "./navigation/up.js"; import { cd } from './navigation/cd.js'; import { ls } from './navigation/ls.js'; +import { cat } from './file-system/cat.js'; export const handleInput = async (line) => { try { @@ -30,9 +31,9 @@ export const handleInput = async (line) => { case COMMANDS.LS.name: await ls(); break; - // case COMMANDS.CAT.name: - // await cat(args); - // break; + case COMMANDS.CAT.name: + await cat(args); + break; // case COMMANDS.ADD.name: // await add(args); // break; From e62d894e874ab5a896ee59ca6f33fb97446f962c Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:06:27 +0300 Subject: [PATCH 16/27] fix: use events instead of pipeline in cat --- src/commands/file-system/cat.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/commands/file-system/cat.js b/src/commands/file-system/cat.js index 8b44980..ecef3c2 100644 --- a/src/commands/file-system/cat.js +++ b/src/commands/file-system/cat.js @@ -1,13 +1,18 @@ import { resolve } from 'path'; import { createReadStream } from 'fs'; -import { pipeline } from 'stream/promises'; +import { EOL } from 'os'; import { getCurrentDir } from '../../utils/directory-path.js'; import { getArgByNumber } from "../../utils/command-input.js"; export const cat = async (args) => { const argPath = getArgByNumber(args, 0); const resolvedPath = resolve(getCurrentDir(), argPath); - const sourceStream = createReadStream(resolvedPath); - await pipeline(sourceStream, process.stdout, { end: false }); + return new Promise((resolve, reject) => { + const readStream = createReadStream(resolvedPath); + + readStream.on('data', (chunk) => process.stdout.write(`${EOL}${chunk.toString()}`)); + readStream.on('end', resolve); + readStream.on('error', (error) => reject(error)); + }); }; \ No newline at end of file From f27a2029ccf6f425bac875fded21a563d5782781 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:13:46 +0300 Subject: [PATCH 17/27] feat: implement add command --- src/commands/file-system/add.js | 12 ++++++++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/commands/file-system/add.js diff --git a/src/commands/file-system/add.js b/src/commands/file-system/add.js new file mode 100644 index 0000000..8f3dcac --- /dev/null +++ b/src/commands/file-system/add.js @@ -0,0 +1,12 @@ +import { basename, resolve } from 'path'; +import { writeFile } from 'fs/promises'; +import { getCurrentDir } from '../../utils/directory-path.js'; +import { getArgByNumber } from "../../utils/command-input.js"; + +export const add = async (args) => { + const argPath = getArgByNumber(args, 0); + const fileBasename = basename(argPath); + const filePath = resolve(getCurrentDir(), fileBasename); + + await writeFile(filePath, '', { flag: 'wx' }); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 8c9f8a7..c939bd4 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -7,6 +7,7 @@ import { up } from "./navigation/up.js"; import { cd } from './navigation/cd.js'; import { ls } from './navigation/ls.js'; import { cat } from './file-system/cat.js'; +import { add } from './file-system/add.js'; export const handleInput = async (line) => { try { @@ -34,9 +35,9 @@ export const handleInput = async (line) => { case COMMANDS.CAT.name: await cat(args); break; - // case COMMANDS.ADD.name: - // await add(args); - // break; + case COMMANDS.ADD.name: + await add(args); + break; // case COMMANDS.RN.name: // await rn(args); // break; From 37080ec82788dad81726152ca2a43f6e2332b414 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:31:35 +0300 Subject: [PATCH 18/27] feat: add rn command --- src/commands/file-system/rn.js | 15 +++++++++++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 src/commands/file-system/rn.js diff --git a/src/commands/file-system/rn.js b/src/commands/file-system/rn.js new file mode 100644 index 0000000..e38a28f --- /dev/null +++ b/src/commands/file-system/rn.js @@ -0,0 +1,15 @@ +import { rename} from 'fs/promises'; +import { basename, resolve, dirname} from 'path'; +import { getCurrentDir } from '../../utils/directory-path.js'; +import { getArgByNumber } from "../../utils/command-input.js"; + +export const rn = async (args) => { + const oldPathArg = getArgByNumber(args, 0); + const newNameArg = getArgByNumber(args, 1); + const newFilename = basename(newNameArg); + const oldFilePath = resolve(getCurrentDir(), oldPathArg); + const fileDir = dirname(oldFilePath); + const newFilePath = resolve(fileDir, newFilename); + + await rename(oldFilePath, newFilePath); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index c939bd4..550cd7b 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -8,6 +8,7 @@ import { cd } from './navigation/cd.js'; import { ls } from './navigation/ls.js'; import { cat } from './file-system/cat.js'; import { add } from './file-system/add.js'; +import { rn } from './file-system/rn.js'; export const handleInput = async (line) => { try { @@ -38,9 +39,9 @@ export const handleInput = async (line) => { case COMMANDS.ADD.name: await add(args); break; - // case COMMANDS.RN.name: - // await rn(args); - // break; + case COMMANDS.RN.name: + await rn(args); + break; // case COMMANDS.CP.name: // await cp(args); // break; From d307094e3dffc9efd8840240b7e4901454027aee Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:13:30 +0300 Subject: [PATCH 19/27] feat: add cp command --- src/commands/file-system/cp.js | 21 +++++++++++++++++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/commands/file-system/cp.js diff --git a/src/commands/file-system/cp.js b/src/commands/file-system/cp.js new file mode 100644 index 0000000..89ce324 --- /dev/null +++ b/src/commands/file-system/cp.js @@ -0,0 +1,21 @@ +import { resolve, basename } from 'path'; +import { createReadStream, createWriteStream } from 'fs'; +import { pipeline } from 'stream/promises'; +import { getCurrentDir } from '../../utils/directory-path.js'; +import { getArgByNumber } from "../../utils/command-input.js"; + +export const cp = async (args) => { + const sourceArgPath = getArgByNumber(args, 0); + const destArgPath = getArgByNumber(args, 1); + + const resolvedSourcePath = resolve(getCurrentDir(), sourceArgPath); + const resolvedDestDirPath = resolve(getCurrentDir(), destArgPath); + + const sourceFilename = basename(resolvedSourcePath); + const resolvedDestFilePath = resolve(resolvedDestDirPath, sourceFilename); + + const sourceStream = createReadStream(resolvedSourcePath); + const destStream = createWriteStream(resolvedDestFilePath, { flags: 'wx' }); + + await pipeline(sourceStream, destStream); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 550cd7b..e9994e9 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -9,6 +9,7 @@ import { ls } from './navigation/ls.js'; import { cat } from './file-system/cat.js'; import { add } from './file-system/add.js'; import { rn } from './file-system/rn.js'; +import { cp } from './file-system/cp.js'; export const handleInput = async (line) => { try { @@ -42,9 +43,9 @@ export const handleInput = async (line) => { case COMMANDS.RN.name: await rn(args); break; - // case COMMANDS.CP.name: - // await cp(args); - // break; + case COMMANDS.CP.name: + await cp(args); + break; // case COMMANDS.MV.name: // await mv(args); // break; From 79613cb0b3ce726c115abd8aa94f0ecb899e2607 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:26:03 +0300 Subject: [PATCH 20/27] feat: add rm command --- src/commands/file-system/rm.js | 11 +++++++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 src/commands/file-system/rm.js diff --git a/src/commands/file-system/rm.js b/src/commands/file-system/rm.js new file mode 100644 index 0000000..ba00b15 --- /dev/null +++ b/src/commands/file-system/rm.js @@ -0,0 +1,11 @@ +import { resolve } from 'path'; +import { unlink } from 'fs/promises'; +import { getCurrentDir } from '../../utils/directory-path.js'; +import { getArgByNumber } from "../../utils/command-input.js"; + +export const rm = async (args) => { + const argPath = getArgByNumber(args, 0); + const filePath = resolve(getCurrentDir(), argPath); + + await unlink(filePath); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index e9994e9..44957b5 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -10,6 +10,7 @@ import { cat } from './file-system/cat.js'; import { add } from './file-system/add.js'; import { rn } from './file-system/rn.js'; import { cp } from './file-system/cp.js'; +import { rm } from './file-system/rm.js'; export const handleInput = async (line) => { try { @@ -49,9 +50,9 @@ export const handleInput = async (line) => { // case COMMANDS.MV.name: // await mv(args); // break; - // case COMMANDS.RM.name: - // await rm(args); - // break; + case COMMANDS.RM.name: + await rm(args); + break; // case COMMANDS.OS.name: // os(args); // break; From a22e689540623930492b5bb18b967efc201c7231 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:32:37 +0300 Subject: [PATCH 21/27] feat: add mv command --- src/commands/file-system/mv.js | 7 +++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/commands/file-system/mv.js diff --git a/src/commands/file-system/mv.js b/src/commands/file-system/mv.js new file mode 100644 index 0000000..d6eb260 --- /dev/null +++ b/src/commands/file-system/mv.js @@ -0,0 +1,7 @@ +import { cp } from './cp.js'; +import { rm } from './rm.js'; + +export const mv = async (args) => { + await cp(args); + await rm(args); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 44957b5..dff6df9 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -11,6 +11,7 @@ import { add } from './file-system/add.js'; import { rn } from './file-system/rn.js'; import { cp } from './file-system/cp.js'; import { rm } from './file-system/rm.js'; +import { mv } from './file-system/mv.js'; export const handleInput = async (line) => { try { @@ -47,9 +48,9 @@ export const handleInput = async (line) => { case COMMANDS.CP.name: await cp(args); break; - // case COMMANDS.MV.name: - // await mv(args); - // break; + case COMMANDS.MV.name: + await mv(args); + break; case COMMANDS.RM.name: await rm(args); break; From 8cc57ca5367f82604d7da5141cf02b7386a87399 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:24:56 +0300 Subject: [PATCH 22/27] feat: add os command --- src/commands/input-handler.js | 7 ++++--- src/commands/os/cpu-info.js | 11 +++++++++++ src/commands/os/os.js | 26 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/commands/os/cpu-info.js create mode 100644 src/commands/os/os.js diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index dff6df9..40f0c03 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -12,6 +12,7 @@ import { rn } from './file-system/rn.js'; import { cp } from './file-system/cp.js'; import { rm } from './file-system/rm.js'; import { mv } from './file-system/mv.js'; +import { executeOsCommand } from './os/os.js'; export const handleInput = async (line) => { try { @@ -54,9 +55,9 @@ export const handleInput = async (line) => { case COMMANDS.RM.name: await rm(args); break; - // case COMMANDS.OS.name: - // os(args); - // break; + case COMMANDS.OS.name: + executeOsCommand(args); + break; // case COMMANDS.HASH.name: // await hash(args); // break; diff --git a/src/commands/os/cpu-info.js b/src/commands/os/cpu-info.js new file mode 100644 index 0000000..4ec8ca1 --- /dev/null +++ b/src/commands/os/cpu-info.js @@ -0,0 +1,11 @@ +import { cpus } from 'os'; + +export const getCpuInfo = () => { + const cpuData = cpus().map((cpu) => ({ + 'Model': cpu.model.trim(), + 'Clock rate, GHz': (cpu.speed / 1000).toFixed(2), + })); + + console.log(`Overall amount of CPUs: ${cpuData.length}`); + console.table(cpuData); +}; \ No newline at end of file diff --git a/src/commands/os/os.js b/src/commands/os/os.js new file mode 100644 index 0000000..c229745 --- /dev/null +++ b/src/commands/os/os.js @@ -0,0 +1,26 @@ +import { EOL, homedir, userInfo } from 'os'; +import { getColoredText } from '../../utils/color-output.js'; +import { getCpuInfo } from './cpu-info.js'; + +export const executeOsCommand = (args) => { + switch (args[0]) { + case '--EOL': + console.log('Default system End-Of-Line:', getColoredText('GREEN', JSON.stringify(EOL))); + break; + case '--cpus': + getCpuInfo() + break; + case '--homedir': + console.log('Home directory:', getColoredText('GREEN', homedir())); + break; + case '--username': + console.log('System user name:', getColoredText('GREEN', userInfo().username)); + break; + case '--architecture': + console.log('CPU architecture:', getColoredText('GREEN', process.arch)); + break; + default: + throw new Error(`Invalid input. Command "os" doesn't support argument "${args[0]}"`); + break; + } +}; \ No newline at end of file From 4b81f11c057e8abf06ffa35eefdc6a846ff63975 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:52:35 +0300 Subject: [PATCH 23/27] feat: add hash command --- src/commands/hash/hash.js | 22 ++++++++++++++++++++++ src/commands/input-handler.js | 7 ++++--- 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/commands/hash/hash.js diff --git a/src/commands/hash/hash.js b/src/commands/hash/hash.js new file mode 100644 index 0000000..2522b5d --- /dev/null +++ b/src/commands/hash/hash.js @@ -0,0 +1,22 @@ +import { resolve } from 'path'; +import { createReadStream } from 'fs'; +import { createHash } from 'crypto'; +import { getArgByNumber } from "../../utils/command-input.js"; +import { getCurrentDir } from '../../utils/directory-path.js'; + +export const calculateHash = async (args) => { + const argPath = getArgByNumber(args, 0); + const resolvedPath = resolve(getCurrentDir(), argPath); + + return new Promise((res, rej) => { + const readStream = createReadStream(resolvedPath); + const hash = createHash('sha256'); + + readStream.on('data', (chunk) => hash.update(chunk)); + readStream.on('end', () => { + console.log(hash.digest('hex')); + res(); + }); + readStream.on('error', (error) => rej(error)); + }); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 40f0c03..3480d21 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -13,6 +13,7 @@ import { cp } from './file-system/cp.js'; import { rm } from './file-system/rm.js'; import { mv } from './file-system/mv.js'; import { executeOsCommand } from './os/os.js'; +import { calculateHash } from './hash/hash.js'; export const handleInput = async (line) => { try { @@ -58,9 +59,9 @@ export const handleInput = async (line) => { case COMMANDS.OS.name: executeOsCommand(args); break; - // case COMMANDS.HASH.name: - // await hash(args); - // break; + case COMMANDS.HASH.name: + await calculateHash(args); + break; // case COMMANDS.COMPRESS.name: // await compress(args); // break; From 74bce0ce80c562dd3d55356745372fc5e931a7e5 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 19:37:57 +0300 Subject: [PATCH 24/27] feat: add archive commands --- src/commands/archive/brotli.js | 21 +++++++++++++++++++++ src/commands/input-handler.js | 13 +++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 src/commands/archive/brotli.js diff --git a/src/commands/archive/brotli.js b/src/commands/archive/brotli.js new file mode 100644 index 0000000..a907a93 --- /dev/null +++ b/src/commands/archive/brotli.js @@ -0,0 +1,21 @@ + +import { resolve } from 'path'; +import { createReadStream, createWriteStream } from 'fs'; +import { pipeline } from 'stream/promises'; +import { createBrotliCompress, createBrotliDecompress } from 'zlib'; +import { getArgByNumber } from "../../utils/command-input.js"; +import { getCurrentDir } from '../../utils/directory-path.js'; + +export const useBrotli = async (args, isCompress = true) => { + const sourceArgPath = getArgByNumber(args, 0); + const destArgPath = getArgByNumber(args, 1); + + const resolvedSourcePath = resolve(getCurrentDir(), sourceArgPath); + const resolvedDestDirPath = resolve(getCurrentDir(), destArgPath); + + const readStream = createReadStream(resolvedSourcePath); + const brotliStream = isCompress ? createBrotliCompress() : createBrotliDecompress(); + const writeStream = createWriteStream(resolvedDestDirPath); + + await pipeline(readStream, brotliStream, writeStream); +}; \ No newline at end of file diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 3480d21..44b6f32 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -14,6 +14,7 @@ import { rm } from './file-system/rm.js'; import { mv } from './file-system/mv.js'; import { executeOsCommand } from './os/os.js'; import { calculateHash } from './hash/hash.js'; +import { useBrotli } from './archive/brotli.js'; export const handleInput = async (line) => { try { @@ -62,12 +63,12 @@ export const handleInput = async (line) => { case COMMANDS.HASH.name: await calculateHash(args); break; - // case COMMANDS.COMPRESS.name: - // await compress(args); - // break; - // case COMMANDS.DECOMPRESS.name: - // await decompress(args); - // break; + case COMMANDS.COMPRESS.name: + await useBrotli(args); + break; + case COMMANDS.DECOMPRESS.name: + await useBrotli(args, false); + break; default: printColoredText('RED', `Invalid input. Command "${command}" not supported.`); break; From 04e97035068bea6253f3b80b6808ef4f520dde8b Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:37:39 +0300 Subject: [PATCH 25/27] fix: use only double quotes as path with spaces delimiter --- src/commands/input-handler.js | 2 +- src/utils/command-input.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index 44b6f32..b64fd7f 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -18,7 +18,7 @@ import { useBrotli } from './archive/brotli.js'; export const handleInput = async (line) => { try { - const args = line.match(/([`"']).*?\1|\S+/g) || []; + const args = line.match(/(").*?\1|\S+/g) || []; const command = args.shift(); checkArgCount(command, args); diff --git a/src/utils/command-input.js b/src/utils/command-input.js index 9b2f0ba..3bfd067 100644 --- a/src/utils/command-input.js +++ b/src/utils/command-input.js @@ -21,7 +21,7 @@ export const trimQuotes = (path) => { if (!path) { return ''; } else { - return path.trim().replace(/^[`"']|[`"']$/g, ''); + return path.trim().replace(/^"|"$/g, ''); } }; From 44c6a94c7246bf79c207befff12b1ad6462b22b0 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:50:29 +0300 Subject: [PATCH 26/27] refactor: add readlineClose function --- src/commands/input-handler.js | 6 ++---- src/index.js | 7 ++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/commands/input-handler.js b/src/commands/input-handler.js index b64fd7f..d2c4214 100644 --- a/src/commands/input-handler.js +++ b/src/commands/input-handler.js @@ -1,7 +1,6 @@ import { EOL } from 'os'; import { checkArgCount, COMMANDS } from "../utils/command-input.js"; import { printColoredText } from "../utils/color-output.js"; -import { printFarewellMessage } from '../utils/user.js'; import { printCurrentDirectory } from "../utils/directory-path.js"; import { up } from "./navigation/up.js"; import { cd } from './navigation/cd.js'; @@ -16,7 +15,7 @@ import { executeOsCommand } from './os/os.js'; import { calculateHash } from './hash/hash.js'; import { useBrotli } from './archive/brotli.js'; -export const handleInput = async (line) => { +export const handleInput = async (line, readlineClose) => { try { const args = line.match(/(").*?\1|\S+/g) || []; const command = args.shift(); @@ -27,8 +26,7 @@ export const handleInput = async (line) => { case undefined: break; case COMMANDS.EXIT.name: - printFarewellMessage(); - process.exit(0); + readlineClose(); break; case COMMANDS.UP.name: up(); diff --git a/src/index.js b/src/index.js index efdf272..4ca01d5 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,11 @@ const init = () => { prompt: getColoredText('BLUE', '> '), }); + const readlineClose = () => { + readline.close(); + process.exit(0); + }; + printWelcomeMessage(); setStartingDir(); printCurrentDirectory(); @@ -18,7 +23,7 @@ const init = () => { readline.on('close', printFarewellMessage); readline.on('line', async (input) => { - await handleInput(input); + await handleInput(input, readlineClose); readline.prompt(); }); }; From ce595c3d887b07bd20afaecadd1f4a0608f03e09 Mon Sep 17 00:00:00 2001 From: Izy <126877709+izy-code@users.noreply.github.com> Date: Tue, 15 Oct 2024 00:40:36 +0300 Subject: [PATCH 27/27] fix: add source path condition to cp and brotli --- src/commands/archive/brotli.js | 6 +++++- src/commands/file-system/cp.js | 10 +++++++--- src/utils/command-input.js | 11 +++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/commands/archive/brotli.js b/src/commands/archive/brotli.js index a907a93..6affb3d 100644 --- a/src/commands/archive/brotli.js +++ b/src/commands/archive/brotli.js @@ -3,7 +3,7 @@ import { resolve } from 'path'; import { createReadStream, createWriteStream } from 'fs'; import { pipeline } from 'stream/promises'; import { createBrotliCompress, createBrotliDecompress } from 'zlib'; -import { getArgByNumber } from "../../utils/command-input.js"; +import { getArgByNumber, isPathAccessible } from "../../utils/command-input.js"; import { getCurrentDir } from '../../utils/directory-path.js'; export const useBrotli = async (args, isCompress = true) => { @@ -13,6 +13,10 @@ export const useBrotli = async (args, isCompress = true) => { const resolvedSourcePath = resolve(getCurrentDir(), sourceArgPath); const resolvedDestDirPath = resolve(getCurrentDir(), destArgPath); + if (!(await isPathAccessible(resolvedSourcePath))) { + throw new Error("Source path is not accessible."); + } + const readStream = createReadStream(resolvedSourcePath); const brotliStream = isCompress ? createBrotliCompress() : createBrotliDecompress(); const writeStream = createWriteStream(resolvedDestDirPath); diff --git a/src/commands/file-system/cp.js b/src/commands/file-system/cp.js index 89ce324..6471223 100644 --- a/src/commands/file-system/cp.js +++ b/src/commands/file-system/cp.js @@ -2,17 +2,21 @@ import { resolve, basename } from 'path'; import { createReadStream, createWriteStream } from 'fs'; import { pipeline } from 'stream/promises'; import { getCurrentDir } from '../../utils/directory-path.js'; -import { getArgByNumber } from "../../utils/command-input.js"; +import { getArgByNumber, isPathAccessible } from "../../utils/command-input.js"; export const cp = async (args) => { const sourceArgPath = getArgByNumber(args, 0); const destArgPath = getArgByNumber(args, 1); const resolvedSourcePath = resolve(getCurrentDir(), sourceArgPath); - const resolvedDestDirPath = resolve(getCurrentDir(), destArgPath); + const resolvedDestDirPath = resolve(getCurrentDir(), destArgPath); + + if (!(await isPathAccessible(resolvedSourcePath))) { + throw new Error("Source path is not accessible."); + } const sourceFilename = basename(resolvedSourcePath); - const resolvedDestFilePath = resolve(resolvedDestDirPath, sourceFilename); + const resolvedDestFilePath = resolve(resolvedDestDirPath, sourceFilename); const sourceStream = createReadStream(resolvedSourcePath); const destStream = createWriteStream(resolvedDestFilePath, { flags: 'wx' }); diff --git a/src/utils/command-input.js b/src/utils/command-input.js index 3bfd067..6f2c1f3 100644 --- a/src/utils/command-input.js +++ b/src/utils/command-input.js @@ -1,4 +1,5 @@ import { EOL } from 'os'; +import { access } from "fs/promises"; export const COMMANDS = { EXIT: { name: '.exit', argCount: 0 }, @@ -44,3 +45,13 @@ export const checkArgCount = (inputCommandName, args) => { } } }; + +export const isPathAccessible = async path => { + try { + await access(path); + + return true; + } catch { + return false; + } +};