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
3 changes: 0 additions & 3 deletions Readme.md

This file was deleted.

5 changes: 5 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
// "compilerOptions": { "checkJs": true },
"typeAcquisition": { "include": ["node"] },
"exclude": ["node_modules"]
}
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 16 additions & 42 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,44 +1,18 @@
{
"name": "node-nodejs-basics",
"version": "1.0.0",
"description": "This repository is the part of nodejs-assignments https://github.com/AlreadyBored/nodejs-assignments",
"engines": {
"node": ">=24.10.0",
"npm": ">=10.9.2"
},
"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"
},
"repository": {
"type": "git",
"url": "git+https://github.com/AlreadyBored/node-nodejs-basics.git"
},
"keywords": [
"nodejs",
"assignments",
"alreadybored"
],
"author": "alreadybored",
"license": "ISC",
"bugs": {
"url": "https://github.com/AlreadyBored/node-nodejs-basics/issues"
},
"homepage": "https://github.com/AlreadyBored/node-nodejs-basics#readme"
"name": "file-manager",
"version": "1.0.0",
"engines": {
"node": ">=24.10.0",
"npm": ">=10.9.2"
},
"type": "module",
"scripts": {
"start": "node src/index.js"
},
"author": "evgkamok",
"license": "ISC",
"bugs": {
"url": "https://github.com/AlreadyBored/nodejs-assignments/issues"
},
"homepage": "https://github.com/AlreadyBored/nodejs-assignments/blob/main/assignments/file-manager/assignment.md"
}
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.

47 changes: 47 additions & 0 deletions src/cli/interface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { createInterface } from 'node:readline/promises'

export function createCLIInterface(username, commandHandler) {
const rl = createInterface({
input: process.stdin,
output: process.stdout,
prompt: '> ',
})

rl.on('line', async input => {
const command = input.trim()

if (command === '.exit') {
rl.close()
return
}

if (command) {
try {
await commandHandler(command)
} catch (error) {
console.log('Operation failed')

if (error.code === 'ENOENT') {
console.log('ENOENT: no such file or directory')
} else {
console.log(error.message)
}
}
}

console.log(`You are currently in ${process.cwd()}`)

rl.prompt()
})

rl.on('close', () => {
console.log(`\nThank you for using File Manager, ${username}, goodbye!`)
process.exit(0)
})

rl.on('SIGINT', () => {
rl.close()
})

return rl
}
26 changes: 26 additions & 0 deletions src/cli/parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { parseArgs } from 'node:util'

export function parseCliArgs() {
try {
const args = process.argv.slice(2)

const options = {
username: {
type: 'string',
},
}

const { values } = parseArgs({ args, options })

if (!values.username) {
return 'user'
} else {
return {
username: values.username,
}
}
} catch (error) {
console.error('Error', error.message)
process.exit(1)
}
}
37 changes: 37 additions & 0 deletions src/commands/compress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createReadStream, createWriteStream } from 'node:fs'
import path from 'node:path'
import { pipeline } from 'node:stream/promises'
import { createGunzip, createGzip } from 'node:zlib'

export async function compress(srcPath, dstPath) {
if (!srcPath && !dstPath) {
throw new Error('Both arguments is required')
}

const absSrcPath = path.resolve(srcPath)
const absDstPath = path.resolve(dstPath)

const source = createReadStream(absSrcPath)
const destination = createWriteStream(absDstPath)
const gzip = createGzip()

await pipeline(source, gzip, destination)
console.log(`Compressed successfully to ${absDstPath}`)
}

export async function decompress(srcPath, dstPath) {
if (!srcPath || !dstPath) {
throw new Error('Both arguments are required')
}

const absSrcPath = path.resolve(srcPath)
const absDstPath = path.resolve(dstPath)

const source = createReadStream(absSrcPath)
const destination = createWriteStream(absDstPath)
const gunZlib = createGunzip()

await pipeline(source, gunZlib, destination)

console.log(`Decompressed successfully to ${absDstPath}`)
}
93 changes: 93 additions & 0 deletions src/commands/files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
readFile,
rename,
writeFile,
copyFile,
unlink,
mkdir as creteDirectory,
} from 'node:fs/promises'
import path from 'node:path'

export async function cat(filePath) {
if (!filePath) {
throw new Error('File path is required')
}

const absFilePath = path.resolve(filePath)
const content = await readFile(absFilePath, 'utf-8')

process.stdout.write(content + '\n')
}

export async function add(fileName) {
if (!fileName) {
throw new Error('File name is required')
}

const filePath = path.join(process.cwd(), fileName)

await writeFile(filePath, '', { flag: 'wx' })

console.log(`File ${fileName} successfully created`)
}

export async function rn(oldFilePath, nameNewFile) {
if (!oldFilePath || !nameNewFile) {
throw new Error('Both arguments are required')
}

const absOldFilePath = path.resolve(oldFilePath)
const nameDirectory = path.dirname(absOldFilePath)
const absNewFilePath = path.join(nameDirectory, nameNewFile)

await rename(absOldFilePath, absNewFilePath)
console.log(`File successfully renamed`)
}

export async function cp(srcPath, destDir) {
if (!srcPath || !destDir) {
throw new Error('Both arguments are required')
}

const absSrcPath = path.resolve(srcPath)
const srcFileName = path.basename(absSrcPath)
const absDestPath = path.resolve(destDir)

const destPath = path.join(absDestPath, srcFileName)

await copyFile(absSrcPath, destPath)
console.log(`File copied successfully`)
}

export async function mv(srcPath, destDir) {
if (!srcPath || !destDir) {
throw new Error('Both arguments are required')
}

const absSrcPath = path.resolve(srcPath)
const absDestPath = path.resolve(destDir)
const srcFileName = path.basename(srcPath)
const targetPath = path.join(absDestPath, srcFileName)

await rename(absSrcPath, targetPath)
console.log(`File moved successfully`)
}

export async function rm(filePath) {
if (!filePath) {
throw new Error('File path argument is required')
}

const absFilePath = path.resolve(filePath)
await unlink(absFilePath)
console.log(`File deleted successfully`)
}

export async function mkdir(nameDir) {
if (!nameDir) {
throw new Error('Name directory is required')
}

await creteDirectory(nameDir)
console.log(`Directory successfully created`)
}
22 changes: 22 additions & 0 deletions src/commands/hash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createHash } from 'node:crypto'
import { createReadStream } from 'node:fs'
import path from 'node:path'

export async function hash(filePath) {
if (!filePath) {
throw new Error('File path is required')
}

const absFilePath = path.resolve(filePath)
const rdStream = createReadStream(absFilePath)

const hash = createHash('sha256')

for await (const chunk of rdStream) {
hash.update(chunk)
}

const hex = hash.digest('hex')
console.log(`SHA-256 hash: ${hex}`)
return hex
}
52 changes: 52 additions & 0 deletions src/commands/navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { readdir } from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'

export async function up() {
const currentDirPath = process.cwd()
process.chdir('..')

if (currentDirPath === process.cwd()) {
console.warn('Already at root directory')
}
}

export async function cd(targetPath) {
if (!targetPath) {
throw new Error('Path is required')
}

const absDstPath = path.resolve(targetPath)
process.chdir(absDstPath)
}

export async function ls() {
const entries = await readdir(process.cwd(), { withFileTypes: true })

const directories = entries
.filter(entry => entry.isDirectory())
.map(entry => ({
Name: entry.name,
Type: 'directory',
}))

const files = entries
.filter(entry => entry.isFile())
.map(entry => ({
Name: entry.name,
Type: 'file',
}))

const contentDir = [...directories, ...files]

console.table(contentDir)

if (directories.length === 0 && files.length === 0) {
console.log('Directory is empty')
}
}

export async function goHomeDir() {
const homePath = os.homedir()
process.chdir(homePath)
}
Loading