@archildata/just-bash 0.1.0 → 0.1.2
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/README.md +13 -1
- package/{bin/shell.ts → dist/shell.js} +54 -93
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -78,7 +78,17 @@ const fs = new ArchilFs(client, {
|
|
|
78
78
|
The package includes an interactive shell for testing:
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
|
|
81
|
+
# Positional arguments (recommended)
|
|
82
|
+
npx @archildata/just-bash aws-us-east-1 myaccount/mydisk
|
|
83
|
+
|
|
84
|
+
# With flags
|
|
85
|
+
npx @archildata/just-bash --region aws-us-east-1 --disk myaccount/mydisk
|
|
86
|
+
|
|
87
|
+
# With token (use env var to keep out of shell history)
|
|
88
|
+
ARCHIL_TOKEN=xxx npx @archildata/just-bash aws-us-east-1 myaccount/mydisk
|
|
89
|
+
|
|
90
|
+
# With debug logging
|
|
91
|
+
npx @archildata/just-bash aws-us-east-1 myaccount/mydisk --log-level debug
|
|
82
92
|
```
|
|
83
93
|
|
|
84
94
|
Shell commands:
|
|
@@ -134,6 +144,8 @@ DEBUG=archil:* node myapp.js
|
|
|
134
144
|
- **Chunked reads** - Large files read in 4 MiB chunks
|
|
135
145
|
- **Native protocol** - Direct Archil protocol access, no FUSE overhead
|
|
136
146
|
|
|
147
|
+
> **Note:** For best performance, run your application in the same region as your Archil disk (e.g., if your disk is in `aws-us-east-1`, deploy your app to AWS us-east-1).
|
|
148
|
+
|
|
137
149
|
## License
|
|
138
150
|
|
|
139
151
|
MIT
|
|
@@ -1,37 +1,44 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
/**
|
|
3
|
-
* Interactive just-bash shell with Archil filesystem
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* ARCHIL_REGION=aws-us-east-1 ARCHIL_DISK=myaccount/mydisk ARCHIL_TOKEN=xxx npx tsx bin/shell.ts
|
|
7
|
-
*/
|
|
1
|
+
#!/usr/bin/env node
|
|
8
2
|
|
|
3
|
+
// bin/shell.ts
|
|
9
4
|
import * as readline from "readline";
|
|
5
|
+
import { Command } from "commander";
|
|
10
6
|
import { ArchilClient } from "@archildata/client";
|
|
11
7
|
import { Bash } from "just-bash";
|
|
12
|
-
import { ArchilFs } from "
|
|
13
|
-
|
|
8
|
+
import { ArchilFs } from "@archildata/just-bash";
|
|
9
|
+
var program = new Command();
|
|
10
|
+
program.name("archil-shell").description("Interactive bash shell with Archil filesystem").version("0.1.0").argument("[region]", "Region identifier (e.g., aws-us-east-1)").argument("[disk]", "Disk name (e.g., myaccount/mydisk)").option("-r, --region <region>", "Region identifier (e.g., aws-us-east-1)").option("-d, --disk <disk>", "Disk name (e.g., myaccount/mydisk)").option("-t, --token <token>", "Auth token (defaults to IAM)").option("-l, --log-level <level>", "Log level: trace, debug, info, warn, error").addHelpText("after", `
|
|
11
|
+
Environment variables:
|
|
12
|
+
ARCHIL_REGION Fallback for --region
|
|
13
|
+
ARCHIL_DISK Fallback for --disk
|
|
14
|
+
ARCHIL_TOKEN Fallback for --token (recommended for secrets)
|
|
15
|
+
ARCHIL_LOG_LEVEL Fallback for --log-level
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
$ npx @archildata/just-bash aws-us-east-1 myaccount/mydisk
|
|
19
|
+
$ npx @archildata/just-bash --region aws-us-east-1 --disk myaccount/mydisk
|
|
20
|
+
$ ARCHIL_TOKEN=xxx npx @archildata/just-bash aws-us-east-1 myaccount/mydisk
|
|
21
|
+
$ npx @archildata/just-bash -r aws-us-east-1 -d myaccount/mydisk -l debug
|
|
22
|
+
`);
|
|
23
|
+
program.parse();
|
|
24
|
+
var opts = program.opts();
|
|
25
|
+
var args = program.args;
|
|
26
|
+
var region = args[0] || opts.region || process.env.ARCHIL_REGION;
|
|
27
|
+
var diskName = args[1] || opts.disk || process.env.ARCHIL_DISK;
|
|
28
|
+
var authToken = opts.token || process.env.ARCHIL_TOKEN;
|
|
29
|
+
var logLevel = opts.logLevel || process.env.ARCHIL_LOG_LEVEL;
|
|
30
|
+
if (!region || !diskName) {
|
|
31
|
+
console.error("Error: region and disk are required\n");
|
|
32
|
+
console.error("Usage:");
|
|
33
|
+
console.error(" npx @archildata/just-bash <region> <disk>");
|
|
34
|
+
console.error(" npx @archildata/just-bash --region <region> --disk <disk>");
|
|
35
|
+
console.error("\nExamples:");
|
|
36
|
+
console.error(" npx @archildata/just-bash aws-us-east-1 myaccount/mydisk");
|
|
37
|
+
console.error(" ARCHIL_TOKEN=xxx npx @archildata/just-bash aws-us-east-1 myaccount/mydisk");
|
|
38
|
+
console.error("\nRun with --help for more options.");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
14
41
|
async function main() {
|
|
15
|
-
const region = process.env.ARCHIL_REGION;
|
|
16
|
-
const diskName = process.env.ARCHIL_DISK;
|
|
17
|
-
const authToken = process.env.ARCHIL_TOKEN;
|
|
18
|
-
const logLevel = process.env.ARCHIL_LOG_LEVEL; // e.g., "debug", "info", "warn", "error", "trace"
|
|
19
|
-
|
|
20
|
-
if (!region || !diskName) {
|
|
21
|
-
console.error("Missing required environment variables:");
|
|
22
|
-
console.error(" ARCHIL_REGION - e.g., aws-us-east-1");
|
|
23
|
-
console.error(" ARCHIL_DISK - e.g., myaccount/mydisk");
|
|
24
|
-
console.error(" ARCHIL_TOKEN - (optional) auth token, defaults to IAM");
|
|
25
|
-
console.error(" ARCHIL_LOG_LEVEL - (optional) log level: trace, debug, info, warn, error");
|
|
26
|
-
console.error("");
|
|
27
|
-
console.error("Usage:");
|
|
28
|
-
console.error(" ARCHIL_REGION=aws-us-east-1 ARCHIL_DISK=myaccount/mydisk npx tsx bin/shell.ts");
|
|
29
|
-
console.error("");
|
|
30
|
-
console.error("For debug logging:");
|
|
31
|
-
console.error(" ARCHIL_LOG_LEVEL=debug ARCHIL_REGION=... ARCHIL_DISK=... npx tsx bin/shell.ts");
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
42
|
console.log("Connecting to Archil...");
|
|
36
43
|
console.log(` Region: ${region}`);
|
|
37
44
|
console.log(` Disk: ${diskName}`);
|
|
@@ -40,57 +47,44 @@ async function main() {
|
|
|
40
47
|
console.log(` Log level: ${logLevel}`);
|
|
41
48
|
}
|
|
42
49
|
console.log("");
|
|
43
|
-
|
|
44
|
-
let client: ArchilClient;
|
|
50
|
+
let client;
|
|
45
51
|
try {
|
|
46
52
|
client = await ArchilClient.connect({
|
|
47
53
|
region,
|
|
48
54
|
diskName,
|
|
49
|
-
authToken: authToken ||
|
|
50
|
-
logLevel
|
|
55
|
+
authToken: authToken || void 0,
|
|
56
|
+
logLevel
|
|
51
57
|
});
|
|
52
58
|
console.log("Connected!");
|
|
53
59
|
} catch (err) {
|
|
54
60
|
console.error("Failed to connect:", err instanceof Error ? err.message : err);
|
|
55
61
|
process.exit(1);
|
|
56
62
|
}
|
|
57
|
-
|
|
58
|
-
// Create filesystem adapter
|
|
59
63
|
const fs = new ArchilFs(client);
|
|
60
|
-
|
|
61
|
-
// Create bash environment
|
|
62
64
|
const bash = new Bash({ fs });
|
|
63
|
-
|
|
64
|
-
// Cleanup function to release delegations and close connection
|
|
65
65
|
let cleaningUp = false;
|
|
66
|
-
const cleanup = async (signal
|
|
66
|
+
const cleanup = async (signal) => {
|
|
67
67
|
if (cleaningUp) return;
|
|
68
68
|
cleaningUp = true;
|
|
69
|
-
|
|
70
69
|
if (signal) {
|
|
71
|
-
console.log(
|
|
70
|
+
console.log(`
|
|
71
|
+
Received ${signal}, cleaning up...`);
|
|
72
72
|
} else {
|
|
73
73
|
console.log("\nGoodbye!");
|
|
74
74
|
}
|
|
75
|
-
|
|
76
75
|
try {
|
|
77
|
-
// close() releases all delegations and cleans up resources
|
|
78
76
|
const released = await client.close();
|
|
79
77
|
if (released > 0) {
|
|
80
|
-
console.log(`Released ${released} delegation${released > 1 ?
|
|
78
|
+
console.log(`Released ${released} delegation${released > 1 ? "s" : ""}`);
|
|
81
79
|
}
|
|
82
80
|
} catch (err) {
|
|
83
81
|
console.error("Error during cleanup:", err instanceof Error ? err.message : err);
|
|
84
82
|
}
|
|
85
|
-
|
|
86
83
|
process.exit(0);
|
|
87
84
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
process.on(
|
|
91
|
-
process.on('SIGTERM', () => cleanup('SIGTERM'));
|
|
92
|
-
process.on('SIGHUP', () => cleanup('SIGHUP'));
|
|
93
|
-
|
|
85
|
+
process.on("SIGINT", () => cleanup("SIGINT"));
|
|
86
|
+
process.on("SIGTERM", () => cleanup("SIGTERM"));
|
|
87
|
+
process.on("SIGHUP", () => cleanup("SIGHUP"));
|
|
94
88
|
console.log("");
|
|
95
89
|
console.log("=== Archil just-bash shell ===");
|
|
96
90
|
console.log("Type bash commands to interact with the filesystem.");
|
|
@@ -101,47 +95,34 @@ async function main() {
|
|
|
101
95
|
console.log(" archil help - Show archil commands");
|
|
102
96
|
console.log("Type 'exit' or Ctrl+D to quit.");
|
|
103
97
|
console.log("");
|
|
104
|
-
|
|
105
|
-
// Create readline interface for interactive input
|
|
106
98
|
const rl = readline.createInterface({
|
|
107
99
|
input: process.stdin,
|
|
108
100
|
output: process.stdout,
|
|
109
|
-
prompt: "archil$ "
|
|
101
|
+
prompt: "archil$ "
|
|
110
102
|
});
|
|
111
|
-
|
|
112
103
|
let cwd = "/";
|
|
113
|
-
|
|
114
104
|
const prompt = () => {
|
|
115
105
|
rl.setPrompt(`archil:${cwd}$ `);
|
|
116
106
|
rl.prompt();
|
|
117
107
|
};
|
|
118
|
-
|
|
119
108
|
prompt();
|
|
120
|
-
|
|
121
|
-
// Helper to resolve a path relative to cwd
|
|
122
|
-
const resolvePath = (path: string): string => {
|
|
109
|
+
const resolvePath = (path) => {
|
|
123
110
|
if (path.startsWith("/")) {
|
|
124
111
|
return path;
|
|
125
112
|
}
|
|
126
113
|
return cwd === "/" ? "/" + path : cwd + "/" + path;
|
|
127
114
|
};
|
|
128
|
-
|
|
129
|
-
// Handle archil checkout/checkin commands
|
|
130
|
-
const handleArchilCommand = async (command: string): Promise<boolean> => {
|
|
115
|
+
const handleArchilCommand = async (command) => {
|
|
131
116
|
const parts = command.split(/\s+/);
|
|
132
117
|
if (parts[0] !== "archil") {
|
|
133
118
|
return false;
|
|
134
119
|
}
|
|
135
|
-
|
|
136
120
|
const subcommand = parts[1];
|
|
137
121
|
const targetPath = parts[2];
|
|
138
|
-
|
|
139
122
|
if (subcommand === "checkout") {
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const pathArg = args.find(a => !a.startsWith("-"));
|
|
144
|
-
|
|
123
|
+
const args2 = parts.slice(2);
|
|
124
|
+
const force = args2.includes("--force") || args2.includes("-f");
|
|
125
|
+
const pathArg = args2.find((a) => !a.startsWith("-"));
|
|
145
126
|
if (!pathArg) {
|
|
146
127
|
console.error("Usage: archil checkout [--force|-f] <path>");
|
|
147
128
|
return true;
|
|
@@ -156,7 +137,6 @@ async function main() {
|
|
|
156
137
|
}
|
|
157
138
|
return true;
|
|
158
139
|
}
|
|
159
|
-
|
|
160
140
|
if (subcommand === "checkin") {
|
|
161
141
|
if (!targetPath) {
|
|
162
142
|
console.error("Usage: archil checkin <path>");
|
|
@@ -172,7 +152,6 @@ async function main() {
|
|
|
172
152
|
}
|
|
173
153
|
return true;
|
|
174
154
|
}
|
|
175
|
-
|
|
176
155
|
if (subcommand === "list-delegations" || subcommand === "delegations") {
|
|
177
156
|
try {
|
|
178
157
|
const delegations = client.listDelegations();
|
|
@@ -189,7 +168,6 @@ async function main() {
|
|
|
189
168
|
}
|
|
190
169
|
return true;
|
|
191
170
|
}
|
|
192
|
-
|
|
193
171
|
if (subcommand === "help" || !subcommand) {
|
|
194
172
|
console.log("Archil commands:");
|
|
195
173
|
console.log(" archil checkout [--force|-f] <path> - Acquire write delegation");
|
|
@@ -200,48 +178,36 @@ async function main() {
|
|
|
200
178
|
console.log("The --force flag revokes any existing delegation from other clients.");
|
|
201
179
|
return true;
|
|
202
180
|
}
|
|
203
|
-
|
|
204
181
|
console.error(`Unknown archil command: ${subcommand}`);
|
|
205
182
|
console.error("Run 'archil help' for available commands");
|
|
206
183
|
return true;
|
|
207
184
|
};
|
|
208
|
-
|
|
209
185
|
rl.on("line", async (line) => {
|
|
210
186
|
const trimmed = line.trim();
|
|
211
|
-
|
|
212
187
|
if (trimmed === "exit" || trimmed === "quit") {
|
|
213
188
|
await cleanup();
|
|
214
189
|
return;
|
|
215
190
|
}
|
|
216
|
-
|
|
217
191
|
if (!trimmed) {
|
|
218
192
|
prompt();
|
|
219
193
|
return;
|
|
220
194
|
}
|
|
221
|
-
|
|
222
|
-
// Pause readline while we process the command
|
|
223
195
|
rl.pause();
|
|
224
|
-
|
|
225
196
|
try {
|
|
226
|
-
// Check for archil commands first
|
|
227
197
|
if (trimmed.startsWith("archil")) {
|
|
228
198
|
await handleArchilCommand(trimmed);
|
|
229
199
|
rl.resume();
|
|
230
200
|
prompt();
|
|
231
201
|
return;
|
|
232
202
|
}
|
|
233
|
-
|
|
234
|
-
// Execute command with current working directory
|
|
235
203
|
const result = await bash.exec(trimmed, {
|
|
236
204
|
cwd,
|
|
237
205
|
env: {
|
|
238
206
|
HOME: "/",
|
|
239
207
|
USER: "archil",
|
|
240
|
-
PWD: cwd
|
|
241
|
-
}
|
|
208
|
+
PWD: cwd
|
|
209
|
+
}
|
|
242
210
|
});
|
|
243
|
-
|
|
244
|
-
// Print output
|
|
245
211
|
if (result.stdout) {
|
|
246
212
|
process.stdout.write(result.stdout);
|
|
247
213
|
if (!result.stdout.endsWith("\n")) {
|
|
@@ -254,22 +220,17 @@ async function main() {
|
|
|
254
220
|
console.error("");
|
|
255
221
|
}
|
|
256
222
|
}
|
|
257
|
-
|
|
258
|
-
// Update cwd if command changed it
|
|
259
223
|
if (result.env?.PWD && result.env.PWD !== cwd) {
|
|
260
224
|
cwd = result.env.PWD;
|
|
261
225
|
}
|
|
262
226
|
} catch (err) {
|
|
263
227
|
console.error("Error:", err instanceof Error ? err.message : err);
|
|
264
228
|
}
|
|
265
|
-
|
|
266
229
|
rl.resume();
|
|
267
230
|
prompt();
|
|
268
231
|
});
|
|
269
|
-
|
|
270
232
|
rl.on("close", () => cleanup());
|
|
271
233
|
}
|
|
272
|
-
|
|
273
234
|
main().catch((err) => {
|
|
274
235
|
console.error("Fatal error:", err);
|
|
275
236
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archildata/just-bash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Archil filesystem adapter for just-bash",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,14 +13,13 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
|
-
"archil-shell": "./
|
|
16
|
+
"archil-shell": "./dist/shell.js"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
|
-
"dist"
|
|
20
|
-
"bin"
|
|
19
|
+
"dist"
|
|
21
20
|
],
|
|
22
21
|
"scripts": {
|
|
23
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
22
|
+
"build": "tsup src/index.ts --format cjs,esm --dts && tsup bin/shell.ts --format esm --outDir dist --no-splitting --external @archildata/just-bash",
|
|
24
23
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
25
24
|
"lint": "eslint src/",
|
|
26
25
|
"typecheck": "tsc --noEmit",
|
|
@@ -28,6 +27,7 @@
|
|
|
28
27
|
},
|
|
29
28
|
"dependencies": {
|
|
30
29
|
"@archildata/client": "^0.1.0",
|
|
30
|
+
"commander": "^14.0.3",
|
|
31
31
|
"debug": "^4.3.4",
|
|
32
32
|
"just-bash": "^2.7.0"
|
|
33
33
|
},
|