Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"editor.formatOnSave": true,
"[javascript]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
}
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "file-manager",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"type": "module",
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Dzmitry Yarmoshkin",
"license": "ISC"
}
17 changes: 17 additions & 0 deletions src/commands/archiving/compress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createReadStream, createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
import { createBrotliCompress } from 'node:zlib';
import { checkFileExists, extractArgument } from '../../utils/utils.js';

export const compress = async (userInput) => {
const sourceFilePath = extractArgument(userInput, 1);
const destFilePath = extractArgument(userInput, 2);

await checkFileExists(sourceFilePath);

const gzip = createBrotliCompress();
const sourceStream = createReadStream(sourceFilePath);
const destStream = createWriteStream(destFilePath);

await pipeline(sourceStream, gzip, destStream);
};
17 changes: 17 additions & 0 deletions src/commands/archiving/decompress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createReadStream, createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
import { createBrotliDecompress } from 'node:zlib';
import { checkFileExists, extractArgument } from '../../utils/utils.js';

export const decompress = async (userInput) => {
const sourceFilePath = extractArgument(userInput, 1);
const destFilePath = extractArgument(userInput, 2);

await checkFileExists(sourceFilePath);

const gzip = createBrotliDecompress();
const sourceStream = createReadStream(sourceFilePath);
const destStream = createWriteStream(destFilePath);

await pipeline(sourceStream, gzip, destStream);
};
49 changes: 49 additions & 0 deletions src/commands/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { extractArgument, extractArguments } from '../utils/utils.js';

export const COMMANDS = {
UP: { commandName: 'up', expectedArgs: 0 },
CD: { commandName: 'cd', expectedArgs: 1 },
LS: { commandName: 'ls', expectedArgs: 0 },
CAT: { commandName: 'cat', expectedArgs: 1 },
ADD: { commandName: 'add', expectedArgs: 1 },
RN: { commandName: 'rn', expectedArgs: 2 },
CP: { commandName: 'cp', expectedArgs: 2 },
MV: { commandName: 'mv', expectedArgs: 2 },
RM: { commandName: 'rm', expectedArgs: 1 },
HASH: { commandName: 'hash', expectedArgs: 1 },
COMPRESS: { commandName: 'compress', expectedArgs: 2 },
DECOMPRESS: { commandName: 'decompress', expectedArgs: 2 },
EXIT: { commandName: '.exit', expectedArgs: 0 },
OS: { commandName: 'os', expectedArgs: 1 },
OS_EOL: { commandName: '--EOL' },
OS_CPUS: { commandName: '--cpus' },
OS_HOMEDIR: { commandName: '--homedir' },
OS_USERNAME: { commandName: '--username' },
OS_ARCH: { commandName: '--architecture' },
};

export const checkArgumentCount = (command, userInput) => {
for (const key in COMMANDS) {
if (COMMANDS[key].commandName === command) {
const expectedArgs = COMMANDS[key].expectedArgs;
const args = extractArguments(userInput);

if (args.length - 1 !== expectedArgs) {
throw new Error(`Incorrect number of arguments provided. Expected ${expectedArgs} arguments.`);
}
}
}
};

export const parseCommand = (userInput) => {
const command = extractArgument(userInput, 0);

checkArgumentCount(command, userInput);

if (command === COMMANDS.OS.commandName) {
const argument = extractArgument(userInput, 1);
return argument;
}

return command;
};
12 changes: 12 additions & 0 deletions src/commands/filesystem/add.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { getCurrentDirectory } from '../../directory.js';
import { extractArgument } from '../../utils/utils.js';

export const add = async (userInput) => {
const parsedFilename = extractArgument(userInput, 1);
const filename = path.basename(parsedFilename);
const filePath = path.resolve(getCurrentDirectory(), filename);

await fs.writeFile(filePath, '', { flag: 'wx' });
};
14 changes: 14 additions & 0 deletions src/commands/filesystem/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createReadStream } from 'node:fs';
import path from 'node:path';
import { stdout } from 'node:process';
import { pipeline } from 'node:stream/promises';
import { getCurrentDirectory } from '../../directory.js';
import { extractArgument } from '../../utils/utils.js';

export const cat = async (userInput) => {
const parsedPath = extractArgument(userInput, 1);
const sourceFilePath = path.resolve(getCurrentDirectory(), parsedPath);
const sourceStream = createReadStream(sourceFilePath);

await pipeline(sourceStream, stdout, { end: false });
};
8 changes: 8 additions & 0 deletions src/commands/filesystem/cd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { chdir } from 'node:process';
import { extractArgument } from '../../utils/utils.js';

export const cd = (userInput) => {
const parsedPath = extractArgument(userInput, 1);

chdir(parsedPath);
};
21 changes: 21 additions & 0 deletions src/commands/filesystem/cp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createReadStream, createWriteStream } from 'node:fs';
import path from 'node:path';
import { pipeline } from 'node:stream/promises';
import { getCurrentDirectory } from '../../directory.js';
import { checkFileExists, extractArgument } from '../../utils/utils.js';

export const cp = async (userInput) => {
const parsedSourcePath = extractArgument(userInput, 1);
const parsedDestPath = extractArgument(userInput, 2);
const sourceFilePath = path.resolve(getCurrentDirectory(), parsedSourcePath);
const destFolderPath = path.resolve(getCurrentDirectory(), parsedDestPath);

await checkFileExists(sourceFilePath);

const sourceFilename = path.basename(sourceFilePath);
const destFilePath = path.resolve(destFolderPath, sourceFilename);
const sourceStream = createReadStream(sourceFilePath);
const destStream = createWriteStream(destFilePath);

await pipeline(sourceStream, destStream);
};
30 changes: 30 additions & 0 deletions src/commands/filesystem/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { getCurrentDirectory } from '../../directory.js';

export const ls = async () => {
const files = await fs.readdir(getCurrentDirectory());
const fileInfoArray = [];

const folders = [];
const filesList = [];
for (const file of files) {
const fileStat = await fs.stat(path.resolve(getCurrentDirectory(), file));
const isFile = fileStat.isFile();
const fileType = isFile ? 'file' : 'directory';
const fileInfo = { Name: file, Type: fileType };

if (fileType === 'directory') {
folders.push(fileInfo);
} else {
filesList.push(fileInfo);
}
}

folders.sort((a, b) => a.Name.localeCompare(b.Name));
filesList.sort((a, b) => a.Name.localeCompare(b.Name));

fileInfoArray.push(...folders, ...filesList);

console.table(fileInfoArray, ['Name', 'Type']);
};
7 changes: 7 additions & 0 deletions src/commands/filesystem/mv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { cp } from './cp.js';
import { rm } from './rm.js';

export const mv = async (userInput) => {
await cp(userInput);
await rm(userInput);
};
11 changes: 11 additions & 0 deletions src/commands/filesystem/rm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { getCurrentDirectory } from '../../directory.js';
import { extractArgument } from '../../utils/utils.js';

export const rm = async (userInput) => {
const parsedSourcePath = extractArgument(userInput, 1);
const sourceFilePath = path.resolve(getCurrentDirectory(), parsedSourcePath);

await fs.unlink(sourceFilePath);
};
16 changes: 16 additions & 0 deletions src/commands/filesystem/rn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { getCurrentDirectory } from '../../directory.js';
import { extractArgument } from '../../utils/utils.js';

export const rn = async (userInput) => {
const parsedSourcePath = extractArgument(userInput, 1);
const parsedDestPath = extractArgument(userInput, 2);

const destFilename = path.basename(parsedDestPath);
const sourceFilePath = path.resolve(getCurrentDirectory(), parsedSourcePath);
const sourceFileDir = path.dirname(sourceFilePath);
const renamedFilePath = path.resolve(sourceFileDir, destFilename);

await fs.rename(sourceFilePath, renamedFilePath);
};
5 changes: 5 additions & 0 deletions src/commands/filesystem/up.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { chdir } from 'node:process';

export const up = () => {
chdir('..');
};
13 changes: 13 additions & 0 deletions src/commands/hash/hash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createHash } from 'node:crypto';
import { createReadStream } from 'node:fs';
import { stdout } from 'node:process';
import { pipeline } from 'node:stream/promises';
import { extractArgument } from '../../utils/utils.js';

export const calculateHash = async (userInput) => {
const sourceFilePath = extractArgument(userInput, 1);
const hash = createHash('sha256');
const input = createReadStream(sourceFilePath);

await pipeline(input, hash.setEncoding('hex'), stdout, { end: false });
};
5 changes: 5 additions & 0 deletions src/commands/os-info/arch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { arch as nodeArch } from 'node:os';

export const arch = () => {
console.log(`Node.js binary architecture: ${nodeArch()}`);
};
14 changes: 14 additions & 0 deletions src/commands/os-info/cpus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { availableParallelism, cpus as nodeCPUS } from 'os';

export const cpus = () => {
const cpuData = nodeCPUS();
const coreCount = availableParallelism();
const cpuInfoArray = [];

console.log(`Number of cores: ${coreCount}`);
cpuData.forEach((core) => {
cpuInfoArray.push({ Model: core.model, Speed: `${(core.speed / 1000).toFixed(2)} GHz` });
});

console.table(cpuInfoArray, ['Model', 'Speed']);
};
5 changes: 5 additions & 0 deletions src/commands/os-info/eol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { EOL } from 'os';

export const eol = () => {
console.log(`System End-Of-Line (EOL): ${JSON.stringify(EOL)}`);
};
5 changes: 5 additions & 0 deletions src/commands/os-info/homedir.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { getHomeDir } from '../../utils/utils.js';

export const homedir = () => {
console.log(`Home directory: ${getHomeDir()}`);
};
6 changes: 6 additions & 0 deletions src/commands/os-info/username.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { userInfo } from 'node:os';

export const username = () => {
const user = userInfo();
console.log(`Current system user name: ${user.username}`);
};
12 changes: 12 additions & 0 deletions src/directory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { chdir, cwd } from 'node:process';
import { getHomeDir } from './utils/utils.js';

export const setStartingDir = () => {
const startingDir = getHomeDir();

chdir(startingDir);
};

export const getCurrentDirectory = () => {
return cwd();
};
13 changes: 13 additions & 0 deletions src/events/exit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { logWithColor } from '../utils/utils.js';

export const setExitEvents = (username) => {
const message = `Thank you for using File Manager, ${username}, goodbye!`;

process.on('SIGINT', () => {
process.exit(0);
});

process.on('exit', () => {
logWithColor(message, 'yellow');
});
};
Loading