mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 03:20:12 +08:00
Feat filegraph (#194)
* feat: update filegraph on touch command * feat: update filegraph on mkdir * feat: add different parsing opts for each command * refactor: replace axios with fetch. put handleCommand to a new file * feat: add config for mounting cli in dev stage * refactor: clean up unused validators * feat: add command handler for copy files. reuse resolvePath function * feat: add rm handler, support specific files deletion. Glob not supported yet * feat: handle discover cases that the folder is actually empty * feat: handle discover empty folder better and support rmdir * feat: handle mv command * refactor: remove unused console logs
This commit is contained in:
1 parent
a732c1d119
commit
f0a09ac4d9
19 files changed
+326
-119
No files matched your search
+18
-34
@@ -1,9 +1,6 @@
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
const fs = require('fs').promises
|
||||
const { exit } = require('process')
|
||||
const minimist = require('minimist')
|
||||
const axios = require('axios')
|
||||
const discoverFiles = require('./discover.js')
|
||||
const handleCommand = require('./handleCommand.js')
|
||||
|
||||
const {
|
||||
API_ENDPOINT,
|
||||
@@ -15,13 +12,6 @@ const {
|
||||
CMD_EXIT_CODE,
|
||||
} = process.env
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: `${API_ENDPOINT}/api/v1`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${TOKEN}`,
|
||||
},
|
||||
})
|
||||
|
||||
async function readOrNone(file) {
|
||||
try {
|
||||
return await fs.readFile(file, 'utf8')
|
||||
@@ -30,28 +20,6 @@ async function readOrNone(file) {
|
||||
}
|
||||
}
|
||||
|
||||
const commandListeners = {
|
||||
ls: [discoverFiles],
|
||||
cd: [changeDirectory],
|
||||
}
|
||||
|
||||
function changeDirectory() {
|
||||
return {
|
||||
pwd: process.cwd(),
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCommand(command) {
|
||||
const argv = minimist(command.split(' '))
|
||||
const name = argv._[0]
|
||||
const listeners = commandListeners[name]
|
||||
if (!listeners) return {}
|
||||
return listeners.reduce(async (result, listener) => {
|
||||
const res = await listener(argv)
|
||||
return { ...res, ...result }
|
||||
}, {})
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (!CMD_NAME) exit(0)
|
||||
|
||||
@@ -67,7 +35,23 @@ async function main() {
|
||||
pwd: PWD,
|
||||
params,
|
||||
}
|
||||
await api.post('/commands', payload)
|
||||
try {
|
||||
const response = await fetch(`${API_ENDPOINT}/api/v1/commands`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${TOKEN}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
if (!response.ok) {
|
||||
console.error(`Failed to send command: ${response.statusText}`)
|
||||
const responseBody = await response.text()
|
||||
console.error(`Response Body: ${responseBody}`)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error occurred while sending command:', e)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
const fs = require('fs').promises
|
||||
const path = require('path')
|
||||
const { resolvePath } = require('./utils')
|
||||
|
||||
async function collectFilesInfo(inputPath, level = 0, hiddenFiles = false) {
|
||||
const stats = await fs.stat(inputPath)
|
||||
const name = path.basename(inputPath)
|
||||
const discovered = level <= 1 && (hiddenFiles || !name.startsWith('.'))
|
||||
const files = [
|
||||
{
|
||||
path: inputPath,
|
||||
name,
|
||||
type: stats.isDirectory() ? 'directory' : 'file',
|
||||
discovered,
|
||||
},
|
||||
]
|
||||
const self = {
|
||||
path: inputPath,
|
||||
name,
|
||||
type: stats.isDirectory() ? 'directory' : 'file',
|
||||
discovered,
|
||||
}
|
||||
const files = [self]
|
||||
if (stats.isDirectory() && level < 2) {
|
||||
try {
|
||||
let entries = await fs.readdir(inputPath)
|
||||
if (entries.length === 0) {
|
||||
self.empty = true
|
||||
return files
|
||||
}
|
||||
if (level > 0) {
|
||||
entries = entries.slice(0, 5)
|
||||
}
|
||||
@@ -37,7 +41,7 @@ async function discoverFiles(argv) {
|
||||
try {
|
||||
const result = await Promise.all(
|
||||
targetPath
|
||||
.map((p) => path.resolve(process.cwd(), p))
|
||||
.map((p) => resolvePath(p))
|
||||
.map((p) => collectFilesInfo(p, 0, argv.a || argv.all))
|
||||
)
|
||||
return { discover: result.flat() }
|
||||
@@ -46,4 +50,7 @@ async function discoverFiles(argv) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = discoverFiles
|
||||
module.exports = {
|
||||
discoverFiles,
|
||||
collectFilesInfo,
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
const fs = require('fs').promises
|
||||
const minimist = require('minimist')
|
||||
const { discoverFiles, collectFilesInfo } = require('./discover')
|
||||
const { resolvePath } = require('./utils')
|
||||
|
||||
const commandListeners = {
|
||||
ls: {
|
||||
opts: {
|
||||
boolean: ['a', 'l', 'h'],
|
||||
},
|
||||
handler: discoverFiles,
|
||||
},
|
||||
cd: {
|
||||
handler: changeDirectory,
|
||||
},
|
||||
touch: {
|
||||
handler: createFiles,
|
||||
},
|
||||
mkdir: {
|
||||
opts: {
|
||||
boolean: ['p'],
|
||||
},
|
||||
handler: createFiles,
|
||||
},
|
||||
cp: {
|
||||
opts: {
|
||||
boolean: ['r'],
|
||||
},
|
||||
handler: copyFiles,
|
||||
},
|
||||
rm: {
|
||||
opts: {
|
||||
boolean: ['r', 'f', 'v'],
|
||||
},
|
||||
handler: removeFiles,
|
||||
},
|
||||
rmdir: {
|
||||
opts: {
|
||||
boolean: ['p', 'v'],
|
||||
},
|
||||
handler: removeFiles,
|
||||
},
|
||||
mv: {
|
||||
handler: moveFiles,
|
||||
},
|
||||
}
|
||||
|
||||
async function handleCommand(command) {
|
||||
const name = command.split(' ')[0]
|
||||
const listener = commandListeners[name]
|
||||
if (!listener) return {}
|
||||
const argv = minimist(command.split(' '), listener.opts)
|
||||
return listener.handler(argv)
|
||||
}
|
||||
|
||||
function changeDirectory() {
|
||||
return {
|
||||
pwd: process.cwd(),
|
||||
}
|
||||
}
|
||||
|
||||
async function createFiles(argv) {
|
||||
const { _ } = argv
|
||||
const files = _.slice(1)
|
||||
const results = []
|
||||
for (const file of files) {
|
||||
const filePath = resolvePath(file)
|
||||
try {
|
||||
const exists = await fs.stat(filePath)
|
||||
if (exists) {
|
||||
results.push({
|
||||
path: filePath,
|
||||
type: exists.isFile() ? 'file' : 'directory',
|
||||
discovered: true,
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
add: results,
|
||||
}
|
||||
}
|
||||
|
||||
async function copyFiles(argv) {
|
||||
const { _ } = argv
|
||||
const files = _.slice(1)
|
||||
if (files.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
const dest = files.pop()
|
||||
const destPath = resolvePath(dest)
|
||||
return {
|
||||
discover: await collectFilesInfo(destPath, 0, true),
|
||||
}
|
||||
}
|
||||
|
||||
async function removeFiles(argv) {
|
||||
const files = argv._.slice(1)
|
||||
const results = []
|
||||
for (const file of files) {
|
||||
const filePath = resolvePath(file)
|
||||
try {
|
||||
await fs.access(filePath, fs.constants.F_OK)
|
||||
} catch {
|
||||
results.push({
|
||||
path: filePath,
|
||||
type: 'file',
|
||||
discovered: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
return {
|
||||
remove: results,
|
||||
}
|
||||
}
|
||||
|
||||
async function moveFiles(argv) {
|
||||
const { _ } = argv
|
||||
const sources = _.slice(1)
|
||||
if (sources.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
const dest = sources.pop()
|
||||
const results = {
|
||||
add: [],
|
||||
remove: [],
|
||||
}
|
||||
// check source
|
||||
for (const source of sources) {
|
||||
const sourcePath = resolvePath(source)
|
||||
try {
|
||||
await fs.access(sourcePath, fs.constants.F_OK)
|
||||
} catch {
|
||||
results.remove.push({
|
||||
path: sourcePath,
|
||||
type: 'file',
|
||||
discovered: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// check dest
|
||||
const destPath = resolvePath(dest)
|
||||
results.add = await collectFilesInfo(destPath, 0, true)
|
||||
return results
|
||||
}
|
||||
|
||||
module.exports = handleCommand
|
||||
@@ -8,7 +8,6 @@
|
||||
"watch": ""
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.8.2",
|
||||
"minimist": "^1.2.8"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
|
||||
function resolvePath(p) {
|
||||
return path.resolve(process.cwd(), p.replace('~', os.homedir()))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolvePath,
|
||||
}
|
||||
Reference in new issue
Block a user