@bashlife/boxbox-beta 69.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/boxbox.js +3 -0
- package/package.json +20 -0
- package/src/commands/JavaScriptRun/Loader.js +47 -0
- package/src/commands/JavaScriptRun/ModuleLoader.js +11 -0
- package/src/commands/JavaScriptRun/index.js +61 -0
- package/src/commands/JavaScriptRun/init.js +34 -0
- package/src/commands/JavaScriptRun/jsRun.js +111 -0
- package/src/commands/awk.js +58 -0
- package/src/commands/basename.js +10 -0
- package/src/commands/cal.js +33 -0
- package/src/commands/call.js +115 -0
- package/src/commands/cat.js +16 -0
- package/src/commands/cd.sh +12 -0
- package/src/commands/chmod.js +27 -0
- package/src/commands/clear.js +3 -0
- package/src/commands/cp.js +17 -0
- package/src/commands/curl.js +80 -0
- package/src/commands/cut.js +42 -0
- package/src/commands/date.js +5 -0
- package/src/commands/df.js +35 -0
- package/src/commands/diff.js +33 -0
- package/src/commands/dirname.js +10 -0
- package/src/commands/du.js +31 -0
- package/src/commands/echo.js +32 -0
- package/src/commands/env.js +38 -0
- package/src/commands/expr.js +97 -0
- package/src/commands/file.js +35 -0
- package/src/commands/find.js +25 -0
- package/src/commands/fmt.js +36 -0
- package/src/commands/fold.js +40 -0
- package/src/commands/grep.js +25 -0
- package/src/commands/groups.js +6 -0
- package/src/commands/head.js +23 -0
- package/src/commands/help.js +41 -0
- package/src/commands/hexdump.js +40 -0
- package/src/commands/hostname.js +5 -0
- package/src/commands/id.js +6 -0
- package/src/commands/info.js +47 -0
- package/src/commands/join.js +40 -0
- package/src/commands/kill.js +17 -0
- package/src/commands/ln.js +33 -0
- package/src/commands/ls.js +8 -0
- package/src/commands/mkdir.js +17 -0
- package/src/commands/mv.js +18 -0
- package/src/commands/od.js +32 -0
- package/src/commands/paste.js +28 -0
- package/src/commands/preview.js +38 -0
- package/src/commands/printenv.js +15 -0
- package/src/commands/printf.js +47 -0
- package/src/commands/ps.js +16 -0
- package/src/commands/pwd.js +3 -0
- package/src/commands/readlink.js +17 -0
- package/src/commands/rm.js +60 -0
- package/src/commands/rmdir.js +28 -0
- package/src/commands/sed.js +103 -0
- package/src/commands/seq.js +17 -0
- package/src/commands/sleep.js +17 -0
- package/src/commands/sort.js +24 -0
- package/src/commands/split.js +30 -0
- package/src/commands/strings.js +26 -0
- package/src/commands/tail.js +23 -0
- package/src/commands/tee.js +22 -0
- package/src/commands/touch.js +12 -0
- package/src/commands/tr.js +33 -0
- package/src/commands/tree.js +47 -0
- package/src/commands/tty.js +7 -0
- package/src/commands/uname.js +33 -0
- package/src/commands/uniq.js +29 -0
- package/src/commands/uptime.js +18 -0
- package/src/commands/version.js +20 -0
- package/src/commands/wc.js +22 -0
- package/src/commands/which.js +24 -0
- package/src/commands/whoami.js +5 -0
- package/src/commands/xargs.js +34 -0
- package/src/commands/yes.js +7 -0
- package/src/index.js +194 -0
package/bin/boxbox.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bashlife/boxbox-beta",
|
|
3
|
+
"version": "69.0.0",
|
|
4
|
+
"description": "A modern BusyBox-style CLI toolkit with custom commands.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "bashlife",
|
|
7
|
+
"bin": {
|
|
8
|
+
"boxbox": "bin/boxbox.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"cli",
|
|
12
|
+
"busybox",
|
|
13
|
+
"toolkit",
|
|
14
|
+
"commands",
|
|
15
|
+
"unix",
|
|
16
|
+
"bash",
|
|
17
|
+
"boxbox"
|
|
18
|
+
],
|
|
19
|
+
"license": "UNLICENSED"
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import vm from "vm";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
|
|
6
|
+
export function loadCommonJS(entry) {
|
|
7
|
+
try {
|
|
8
|
+
const code = fs.readFileSync(entry, "utf8");
|
|
9
|
+
|
|
10
|
+
const module = {
|
|
11
|
+
exports: {}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const dirname = path.dirname(entry);
|
|
15
|
+
const filename = entry;
|
|
16
|
+
|
|
17
|
+
const require = createRequire(entry);
|
|
18
|
+
|
|
19
|
+
const wrapped = `
|
|
20
|
+
(function(
|
|
21
|
+
require,
|
|
22
|
+
module,
|
|
23
|
+
exports,
|
|
24
|
+
__filename,
|
|
25
|
+
__dirname
|
|
26
|
+
) {
|
|
27
|
+
${code}
|
|
28
|
+
});
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const script = vm.runInThisContext(wrapped);
|
|
32
|
+
|
|
33
|
+
script(
|
|
34
|
+
require,
|
|
35
|
+
module,
|
|
36
|
+
module.exports,
|
|
37
|
+
filename,
|
|
38
|
+
dirname
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return module.exports;
|
|
42
|
+
|
|
43
|
+
} catch (err) {
|
|
44
|
+
console.error(`Loader: ${err.message}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
export default async function javascriptRun(args) {
|
|
10
|
+
const command = args[0];
|
|
11
|
+
|
|
12
|
+
if (!command) {
|
|
13
|
+
console.log("javascript: missing command");
|
|
14
|
+
console.log("Usage: boxbox javascript <init|run>");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (command === "init") {
|
|
19
|
+
const projectRoot = process.cwd();
|
|
20
|
+
|
|
21
|
+
const srcDir = path.join(projectRoot, "src");
|
|
22
|
+
const configPath = path.join(projectRoot, "jsrun.yaml");
|
|
23
|
+
|
|
24
|
+
if (!fs.existsSync(srcDir)) {
|
|
25
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!fs.existsSync(configPath)) {
|
|
29
|
+
fs.writeFileSync(
|
|
30
|
+
configPath,
|
|
31
|
+
`type: module\nentry: app.js\n`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log("JavaScriptRun project initialized");
|
|
36
|
+
console.log("Created:");
|
|
37
|
+
console.log(" src/");
|
|
38
|
+
console.log(" jsrun.yaml");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (command === "run") {
|
|
43
|
+
const runtime = path.join(__dirname, "jsRun.js");
|
|
44
|
+
|
|
45
|
+
const child = spawn(
|
|
46
|
+
process.execPath,
|
|
47
|
+
[runtime],
|
|
48
|
+
{
|
|
49
|
+
stdio: "inherit"
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
child.on("error", err => {
|
|
54
|
+
console.log(`javascript run error: ${err.message}`);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(`javascript: unknown command '${command}'`);
|
|
61
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export default function init() {
|
|
5
|
+
const root = process.cwd();
|
|
6
|
+
|
|
7
|
+
const srcDir = path.join(root, "src");
|
|
8
|
+
const configFile = path.join(root, "jsrun.yaml");
|
|
9
|
+
const appFile = path.join(root, "app.js");
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync(srcDir)) {
|
|
12
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(configFile)) {
|
|
16
|
+
fs.writeFileSync(
|
|
17
|
+
configFile,
|
|
18
|
+
`type: module\nentry: app.js\n`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!fs.existsSync(appFile)) {
|
|
23
|
+
fs.writeFileSync(
|
|
24
|
+
appFile,
|
|
25
|
+
`console.log("Hello from jsRun");\n`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log("JavaScriptRun initialized");
|
|
30
|
+
console.log("Created:");
|
|
31
|
+
console.log(" src/");
|
|
32
|
+
console.log(" jsrun.yaml");
|
|
33
|
+
console.log(" app.js");
|
|
34
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
import { loadCommonJS } from "./Loader.js";
|
|
5
|
+
import { loadModule } from "./ModuleLoader.js";
|
|
6
|
+
|
|
7
|
+
function findProjectRoot() {
|
|
8
|
+
let current = process.cwd();
|
|
9
|
+
|
|
10
|
+
while (current !== path.dirname(current)) {
|
|
11
|
+
if (fs.existsSync(path.join(current, "jsrun.yaml"))) {
|
|
12
|
+
return current;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
current = path.dirname(current);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return process.cwd();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseYaml(content) {
|
|
22
|
+
const config = {};
|
|
23
|
+
|
|
24
|
+
for (const line of content.split("\n")) {
|
|
25
|
+
const trimmed = line.trim();
|
|
26
|
+
|
|
27
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const separator = trimmed.indexOf(":");
|
|
32
|
+
|
|
33
|
+
if (separator === -1) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const key = trimmed
|
|
38
|
+
.slice(0, separator)
|
|
39
|
+
.trim();
|
|
40
|
+
|
|
41
|
+
let value = trimmed
|
|
42
|
+
.slice(separator + 1)
|
|
43
|
+
.trim();
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
47
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
48
|
+
) {
|
|
49
|
+
value = value.slice(1, -1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
config[key] = value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return config;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readConfig(root) {
|
|
59
|
+
const configPath = path.join(root, "jsrun.yaml");
|
|
60
|
+
|
|
61
|
+
if (!fs.existsSync(configPath)) {
|
|
62
|
+
throw new Error("jsrun.yaml not found");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const content = fs.readFileSync(
|
|
66
|
+
configPath,
|
|
67
|
+
"utf8"
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return parseYaml(content);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function main() {
|
|
74
|
+
try {
|
|
75
|
+
const root = findProjectRoot();
|
|
76
|
+
|
|
77
|
+
const config = readConfig(root);
|
|
78
|
+
|
|
79
|
+
const entry = path.resolve(
|
|
80
|
+
root,
|
|
81
|
+
config.entry || "app.js"
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (!fs.existsSync(entry)) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`entry file not found: ${entry}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const type = config.type || "module";
|
|
91
|
+
|
|
92
|
+
if (type === "commonjs") {
|
|
93
|
+
loadCommonJS(entry);
|
|
94
|
+
} else if (type === "module") {
|
|
95
|
+
await loadModule(entry);
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`unsupported type: ${type}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
} catch (err) {
|
|
103
|
+
console.error(
|
|
104
|
+
`jsRun: ${err.message}`
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
main();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export default function awk(args) {
|
|
4
|
+
let separator = /\s+/;
|
|
5
|
+
let program = null;
|
|
6
|
+
let file = null;
|
|
7
|
+
|
|
8
|
+
for (let i = 0; i < args.length; i++) {
|
|
9
|
+
if (args[i] === "-F") {
|
|
10
|
+
const next = args[i + 1];
|
|
11
|
+
if (next) {
|
|
12
|
+
separator = new RegExp(next);
|
|
13
|
+
i++;
|
|
14
|
+
}
|
|
15
|
+
} else if (!program) {
|
|
16
|
+
program = args[i];
|
|
17
|
+
} else {
|
|
18
|
+
file = args[i];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!program || !file) {
|
|
23
|
+
console.log("Usage: awk [-F delimiter] '{print $n}' file");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!fs.existsSync(file)) {
|
|
28
|
+
console.log(`awk: ${file}: No such file`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const text = fs.readFileSync(file, "utf8");
|
|
33
|
+
|
|
34
|
+
const match = program.match(/print\s+\$(\d+|0)/);
|
|
35
|
+
|
|
36
|
+
if (!match) {
|
|
37
|
+
console.log("awk: unsupported expression");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const field = match[1];
|
|
42
|
+
|
|
43
|
+
const lines = text.split("\n");
|
|
44
|
+
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
if (field === "0") {
|
|
47
|
+
console.log(line);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const parts = line.split(separator);
|
|
52
|
+
const index = Number(field) - 1;
|
|
53
|
+
|
|
54
|
+
if (parts[index] !== undefined) {
|
|
55
|
+
console.log(parts[index]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default function cal() {
|
|
2
|
+
const now = new Date();
|
|
3
|
+
|
|
4
|
+
const month = now.getMonth();
|
|
5
|
+
const year = now.getFullYear();
|
|
6
|
+
|
|
7
|
+
const name = now.toLocaleString("en-US", { month: "long" });
|
|
8
|
+
|
|
9
|
+
console.log(` ${name} ${year}`);
|
|
10
|
+
console.log("Su Mo Tu We Th Fr Sa");
|
|
11
|
+
|
|
12
|
+
const first = new Date(year, month, 1).getDay();
|
|
13
|
+
const days = new Date(year, month + 1, 0).getDate();
|
|
14
|
+
|
|
15
|
+
let line = "";
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < first; i++) {
|
|
18
|
+
line += " ";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (let day = 1; day <= days; day++) {
|
|
22
|
+
line += String(day).padStart(2, " ") + " ";
|
|
23
|
+
|
|
24
|
+
if ((first + day) % 7 === 0) {
|
|
25
|
+
console.log(line);
|
|
26
|
+
line = "";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (line) {
|
|
31
|
+
console.log(line);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export default async function(args) {
|
|
4
|
+
let method = null;
|
|
5
|
+
let url = null;
|
|
6
|
+
let body = null;
|
|
7
|
+
|
|
8
|
+
const headers = {};
|
|
9
|
+
const formData = new FormData();
|
|
10
|
+
let hasForm = false;
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < args.length; i++) {
|
|
13
|
+
const arg = args[i];
|
|
14
|
+
|
|
15
|
+
if (arg === "-H" || arg === "--header") {
|
|
16
|
+
const header = args[++i];
|
|
17
|
+
|
|
18
|
+
if (!header) continue;
|
|
19
|
+
|
|
20
|
+
const split = header.indexOf(":");
|
|
21
|
+
|
|
22
|
+
if (split !== -1) {
|
|
23
|
+
const key = header.slice(0, split).trim();
|
|
24
|
+
const value = header.slice(split + 1).trim();
|
|
25
|
+
|
|
26
|
+
headers[key] = value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
else if (arg === "-F" || arg === "--form") {
|
|
31
|
+
const form = args[++i];
|
|
32
|
+
|
|
33
|
+
if (!form) continue;
|
|
34
|
+
|
|
35
|
+
hasForm = true;
|
|
36
|
+
|
|
37
|
+
const split = form.indexOf("=");
|
|
38
|
+
|
|
39
|
+
if (split !== -1) {
|
|
40
|
+
const name = form.slice(0, split);
|
|
41
|
+
const value = form.slice(split + 1);
|
|
42
|
+
|
|
43
|
+
if (value.startsWith("@")) {
|
|
44
|
+
const filePath = value.slice(1);
|
|
45
|
+
|
|
46
|
+
const file = fs.readFileSync(filePath);
|
|
47
|
+
|
|
48
|
+
formData.append(
|
|
49
|
+
name,
|
|
50
|
+
new Blob([file]),
|
|
51
|
+
filePath.split("/").pop()
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
formData.append(name, value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
else if (!method) {
|
|
60
|
+
method = arg.toUpperCase();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
else if (!url) {
|
|
64
|
+
url = arg;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
else if (!body) {
|
|
68
|
+
body = arg;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!method || !url) {
|
|
73
|
+
console.log(`
|
|
74
|
+
Usage:
|
|
75
|
+
boxbox call METHOD URL [body]
|
|
76
|
+
|
|
77
|
+
Options:
|
|
78
|
+
-H, --header "Name: Value"
|
|
79
|
+
-F, --form "name=value"
|
|
80
|
+
-F, --form "file=@path"
|
|
81
|
+
`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const options = {
|
|
87
|
+
method,
|
|
88
|
+
headers
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (hasForm) {
|
|
92
|
+
options.body = formData;
|
|
93
|
+
|
|
94
|
+
// Let fetch set multipart boundary automatically
|
|
95
|
+
delete options.headers["Content-Type"];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
else if (body && method !== "GET" && method !== "HEAD") {
|
|
99
|
+
options.body = body;
|
|
100
|
+
|
|
101
|
+
if (!options.headers["Content-Type"]) {
|
|
102
|
+
options.headers["Content-Type"] = "application/json";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const response = await fetch(url, options);
|
|
107
|
+
|
|
108
|
+
console.log(`HTTP ${response.status}`);
|
|
109
|
+
|
|
110
|
+
console.log(await response.text());
|
|
111
|
+
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.log(`call: ${err.message}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export default function(args) {
|
|
4
|
+
const file = args[0];
|
|
5
|
+
|
|
6
|
+
if (!file) {
|
|
7
|
+
console.log("Usage: cat <file>");
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
console.log(fs.readFileSync(file, "utf8"));
|
|
13
|
+
} catch (err) {
|
|
14
|
+
console.log(`cat: ${err.message}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export default function(args) {
|
|
4
|
+
if (args.length < 2) {
|
|
5
|
+
console.log("Usage: chmod <mode> <file>");
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const mode = args[0];
|
|
10
|
+
const file = args[1];
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const permissions = parseInt(mode, 8);
|
|
14
|
+
|
|
15
|
+
if (isNaN(permissions)) {
|
|
16
|
+
console.log(`chmod: invalid mode '${mode}'`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fs.chmodSync(file, permissions);
|
|
21
|
+
|
|
22
|
+
console.log(`Changed permissions of ${file} to ${mode}`);
|
|
23
|
+
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.log(`chmod: ${err.message}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export default function(args) {
|
|
4
|
+
const src = args[0];
|
|
5
|
+
const dest = args[1];
|
|
6
|
+
|
|
7
|
+
if (!src || !dest) {
|
|
8
|
+
console.log("Usage: cp <source> <destination>");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
fs.copyFileSync(src, dest);
|
|
14
|
+
} catch (err) {
|
|
15
|
+
console.log(`cp: ${err.message}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export default async function(args) {
|
|
5
|
+
let method = "GET";
|
|
6
|
+
let url = null;
|
|
7
|
+
let body = null;
|
|
8
|
+
let outputFile = false;
|
|
9
|
+
let headers = {
|
|
10
|
+
"Content-Type": "application/json"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i < args.length; i++) {
|
|
14
|
+
const arg = args[i];
|
|
15
|
+
|
|
16
|
+
if (arg === "-X" || arg === "--request") {
|
|
17
|
+
method = args[++i].toUpperCase();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
else if (arg === "-O") {
|
|
21
|
+
outputFile = true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
else if (arg === "-H" || arg === "--header") {
|
|
25
|
+
const header = args[++i];
|
|
26
|
+
const split = header.indexOf(":");
|
|
27
|
+
|
|
28
|
+
if (split !== -1) {
|
|
29
|
+
const key = header.slice(0, split).trim();
|
|
30
|
+
const value = header.slice(split + 1).trim();
|
|
31
|
+
|
|
32
|
+
headers[key] = value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
else if (arg === "-d" || arg === "--data") {
|
|
37
|
+
body = args[++i];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
else if (!url) {
|
|
41
|
+
url = arg;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!url) {
|
|
46
|
+
console.log("Usage: curl [-X METHOD] [-O] [-H header] [-d data] <url>");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const options = {
|
|
52
|
+
method,
|
|
53
|
+
headers
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (body) {
|
|
57
|
+
options.body = body;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const response = await fetch(url, options);
|
|
61
|
+
|
|
62
|
+
console.log(`HTTP ${response.status}`);
|
|
63
|
+
|
|
64
|
+
if (outputFile) {
|
|
65
|
+
const filename = path.basename(new URL(url).pathname) || "download";
|
|
66
|
+
|
|
67
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
68
|
+
|
|
69
|
+
fs.writeFileSync(filename, buffer);
|
|
70
|
+
|
|
71
|
+
console.log(`Saved ${filename}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.log(await response.text());
|
|
76
|
+
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.log(`curl: ${err.message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|