@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 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
- ARCHIL_REGION=aws-us-east-1 ARCHIL_DISK=myaccount/mydisk ARCHIL_TOKEN=xxx npx @archildata/just-bash
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 npx tsx
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 "../src/ArchilFs.js";
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 || undefined,
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?: string) => {
66
+ const cleanup = async (signal) => {
67
67
  if (cleaningUp) return;
68
68
  cleaningUp = true;
69
-
70
69
  if (signal) {
71
- console.log(`\nReceived ${signal}, cleaning up...`);
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 ? 's' : ''}`);
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
- // Handle signals for graceful shutdown
90
- process.on('SIGINT', () => cleanup('SIGINT'));
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
- // Parse flags and path
141
- const args = parts.slice(2);
142
- const force = args.includes("--force") || args.includes("-f");
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.0",
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": "./bin/shell.ts"
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
  },