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
119 changes: 117 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,118 @@
# Node.js basics
# Assignment: File Manager

## !!! Please don't submit Pull Requests to this repository !!!
## Description

Your task is to implement File Manager using Node.js APIs.

The file manager should be able to do the following:

- Work using CLI
- Perform basic file operations (copy, move, delete, rename, etc.)
- Utilize Streams API
- Get information about the host machine operating system
- Perform hash calculations
- Compress and decompress files

## Technical requirements

- No external dependencies should be required
- Use 20 LTS version of Node.js
- The program is started by npm-script `start` in following way:

```bash
npm run start -- --username=your_username
```

- After starting the program displays the following text in the console (`Username` is equal to value that was passed on application start in `--username` CLI argument)
`Welcome to the File Manager, Username!`
- After program work finished (`ctrl + c` pressed or user sent `.exit` command into console) the program displays the following text in the console
`Thank you for using File Manager, Username, goodbye!`
- At the start of the program and after each end of input/operation current working directory should be printed in following way:
`You are currently in path_to_working_directory`
- Starting working directory is current user's home directory (for example, on Windows it's something like `system_drive/Users/Username`)
- By default program should prompt user in console to print commands and wait for results
- In case of unknown operation or invalid input (missing mandatory arguments, wrong data in arguments, etc.) `Invalid input` message should be shown and user should be able to enter another command
- In case of error during execution of operation `Operation failed` message should be shown and user should be able to enter another command (e.g. attempt to perform an operation on a non-existent file or work on a non-existent path should result in the operation fail)
- User can't go upper than root directory (e.g. on Windows it's current local drive root). If user tries to do so, current working directory doesn't change

List of operations and their syntax:

- Navigation & working directory (nwd)
- Go upper from current directory (when you are in the root folder this operation shouldn't change working directory)
```bash
up
```
- Go to dedicated folder from current directory (`path_to_directory` can be relative or absolute)
```bash
cd path_to_directory
```
- Print in console list of all files and folders in current directory. List should contain:
- list should contain files and folder names (for files - with extension)
- folders and files are sorted in alphabetical order ascending, but list of folders goes first
- type of directory content should be marked explicitly (e.g. as a corresponding column value)
```bash
ls
```
Example of how `ls` command output may look like
![ls output example](./ls-example.JPG)
- Basic operations with files
- Read file and print it's content in console (should be done using Readable stream):
```bash
cat path_to_file
```
- Create empty file in current working directory:
```bash
add new_file_name
```
- Rename file (content should remain unchanged):
```bash
rn path_to_file new_filename
```
- Copy file (should be done using Readable and Writable streams):
```bash
cp path_to_file path_to_new_directory
```
- Move file (same as copy but initial file is deleted, copying part should be done using Readable and Writable streams):
```bash
mv path_to_file path_to_new_directory
```
- Delete file:
```bash
rm path_to_file
```
- Operating system info (prints following information in console)
- Get EOL (default system End-Of-Line) and print it to console
```bash
os --EOL
```
- Get host machine CPUs info (overall amount of CPUS plus model and clock rate (in GHz) for each of them) and print it to console
```bash
os --cpus
```
- Get home directory and print it to console
```bash
os --homedir
```
- Get current _system user name_ (Do not confuse with the username that is set when the application starts) and print it to console
```bash
os --username
```
- Get CPU architecture for which Node.js binary has compiled and print it to console
```bash
os --architecture
```
- Hash calculation
- Calculate hash for file and print it into console
```bash
hash path_to_file
```
- Compress and decompress operations
- Compress file (using Brotli algorithm, should be done using Streams API)
```bash
compress path_to_file path_to_destination
```
- Decompress file (using Brotli algorithm, should be done using Streams API)
```bash
decompress path_to_file path_to_destination
```
NB! After decompressing of previously compressed file result should not differ with originally compressed file
29 changes: 6 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,20 @@
},
"type": "module",
"scripts": {
"cli:args": "node src/cli/args.js --some-arg value1 --other 1337 --arg2 42",
"cli:env": "npx cross-env SOME=any RSS_foo=bar RSS_bar=baz node src/cli/env.js",
"cp": "node src/cp/cp.js",
"fs:copy": "node src/fs/copy.js",
"fs:create": "node src/fs/create.js",
"fs:delete": "node src/fs/delete.js",
"fs:list": "node src/fs/list.js",
"fs:read": "node src/fs/read.js",
"fs:rename": "node src/fs/rename.js",
"hash": "node src/hash/calcHash.js",
"modules": "node src/modules/esm.mjs",
"streams:read": "node src/streams/read.js",
"streams:transform": "node src/streams/transform.js",
"streams:write": "node src/streams/write.js",
"wt": "node src/wt/main.js",
"zip:compress": "node src/zip/compress.js",
"zip:decompress": "node src/zip/decompress.js"
"start": "node src/index.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/AlreadyBored/node-nodejs-basics.git"
"url": "git+https://github.com/Opty1712/node-nodejs-basics.git"
},
"keywords": [
"nodejs",
"assignments",
"alreadybored"
"assignments"
],
"author": "alreadybored",
"author": "Opty1712",
"license": "ISC",
"bugs": {
"url": "https://github.com/AlreadyBored/node-nodejs-basics/issues"
"url": "https://github.com/Opty1712/node-nodejs-basics/issues"
},
"homepage": "https://github.com/AlreadyBored/node-nodejs-basics#readme"
"homepage": "https://github.com/Opty1712/node-nodejs-basics#readme"
}
5 changes: 0 additions & 5 deletions src/cli/args.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/cli/env.js

This file was deleted.

6 changes: 0 additions & 6 deletions src/cp/cp.js

This file was deleted.

12 changes: 0 additions & 12 deletions src/cp/files/script.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/fs/copy.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/fs/create.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/fs/delete.js

This file was deleted.

1 change: 0 additions & 1 deletion src/fs/files/dontLookAtMe.txt

This file was deleted.

7 changes: 0 additions & 7 deletions src/fs/files/fileToRead.txt

This file was deleted.

1 change: 0 additions & 1 deletion src/fs/files/fileToRemove.txt

This file was deleted.

1 change: 0 additions & 1 deletion src/fs/files/hello.txt

This file was deleted.

3 changes: 0 additions & 3 deletions src/fs/files/wrongFilename.txt

This file was deleted.

5 changes: 0 additions & 5 deletions src/fs/list.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/fs/read.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/fs/rename.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/hash/calcHash.js

This file was deleted.

1 change: 0 additions & 1 deletion src/hash/files/fileToCalculateHashFor.txt

This file was deleted.

19 changes: 19 additions & 0 deletions src/helpers/archive/compress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createReadStream, createWriteStream } from "fs";
import { createBrotliCompress } from "zlib";

export const compress = async (fileFrom, fileTo) => {
return new Promise((resolve, reject) => {
const brotli = createBrotliCompress();
const rs = createReadStream(fileFrom);
const ws = createWriteStream(fileTo);

rs.pipe(brotli).pipe(ws);

rs.on("end", () => {
console.log("File compressed");
resolve();
});

rs.on("error", reject);
});
};
19 changes: 19 additions & 0 deletions src/helpers/archive/decompress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createReadStream, createWriteStream } from "fs";
import { createBrotliDecompress } from "zlib";

export const decompress = async (fileFrom, fileTo) => {
return new Promise((resolve, reject) => {
const brotli = createBrotliDecompress();
const rs = createReadStream(fileFrom);
const ws = createWriteStream(fileTo);

rs.pipe(brotli).pipe(ws);

rs.on("end", () => {
console.log("File decompressed");
resolve();
});

rs.on("error", reject);
});
};
2 changes: 2 additions & 0 deletions src/helpers/archive/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { compress } from "./compress.js";
export { decompress } from "./decompress.js";
14 changes: 14 additions & 0 deletions src/helpers/checkIsFileExists.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { access } from "node:fs/promises";

export const checkIsFileExists = async (file, isWarningOnAbsence = true) => {
try {
await access(file);
return true;
} catch (e) {
if (e.code === "ENOENT" && isWarningOnAbsence) {
console.log(`\x1b[33mFile «${file}» does not exist\x1b[0m`);
}

return false;
}
};
29 changes: 29 additions & 0 deletions src/helpers/crypto/getHash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createHash } from "crypto";
import { createReadStream } from "fs";
import { checkIsFileExists } from "../checkIsFileExists.js";

export const getHash = async (file) => {
return new Promise(async (resolve, reject) => {
const isFileExists = await checkIsFileExists(file);

if (!isFileExists) {
reject();
}

const hash = createHash("sha256");
const rs = createReadStream(file);

rs.on("readable", () => {
const data = rs.read();

if (data) {
hash.update(data);
} else {
console.log(`${hash.digest("hex")}`);
resolve();
}
});

rs.on("error", reject);
});
};
1 change: 1 addition & 0 deletions src/helpers/crypto/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getHash } from "./getHash.js";
4 changes: 4 additions & 0 deletions src/helpers/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const operationFailed = "Operation failed";
export const invalidInput = "Invalid input";
export const pathWarning =
'\x1b[33mIf any path contains spaces → use quotes for all paths, f.e. «cp "my dir/my file.js" "dest.js"»\x1b[0m';
6 changes: 6 additions & 0 deletions src/helpers/exit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { EOL } from "./os/EOL.js";

export const exit = (userName) => {
console.log(`${EOL}Thank you for using File Manager, ${userName}, goodbye!`);
process.exit(0);
};
Loading