@archildata/just-bash 0.8.18 → 0.8.19
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/dist/index.cjs +633 -678
- package/dist/index.d.cts +131 -136
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +210 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/shell.mjs +319 -0
- package/dist/shell.mjs.map +1 -0
- package/dist/src-zhIdm_Vq.mjs +622 -0
- package/dist/src-zhIdm_Vq.mjs.map +1 -0
- package/package.json +19 -18
- package/dist/index.d.ts +0 -215
- package/dist/index.js +0 -652
- package/dist/shell.js +0 -313
package/dist/shell.js
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// bin/shell.ts
|
|
4
|
-
import * as readline from "readline";
|
|
5
|
-
import { Command } from "commander";
|
|
6
|
-
import { ArchilClient } from "@archildata/native";
|
|
7
|
-
import { Archil } from "disk";
|
|
8
|
-
import { Bash } from "just-bash";
|
|
9
|
-
import { ArchilFs, createArchilCommand } from "@archildata/just-bash";
|
|
10
|
-
var program = new Command();
|
|
11
|
-
program.name("archil-shell").description("Interactive bash shell with Archil filesystem").version("0.1.0").argument("[target]", "S3 bucket (s3://bucket) or region (e.g., aws-us-east-1)").argument("[disk]", "Disk name (e.g., myaccount/mydisk) - only when target is region").option("-r, --region <region>", "Region identifier (e.g., aws-us-east-1)").option("-d, --disk <disk>", "Disk name (e.g., myaccount/mydisk)").option("-k, --api-key <key>", "API key for disk management (required for S3 bucket mode)").option("-t, --token <token>", "Auth token for direct connection (defaults to IAM)").option("-l, --log-level <level>", "Log level: trace, debug, info, warn, error").option("--bucket-region <region>", "AWS region for the S3 bucket (default: us-east-1)").option("--bucket-prefix <prefix>", "Path prefix within the bucket").addHelpText("after", `
|
|
12
|
-
Quick Start (S3 bucket mode):
|
|
13
|
-
Connect directly to an S3 bucket - creates a disk if needed:
|
|
14
|
-
$ npx @archildata/just-bash s3://my-bucket --api-key adt_xxx
|
|
15
|
-
$ npx @archildata/just-bash s3://my-bucket --api-key adt_xxx --bucket-region us-west-2
|
|
16
|
-
|
|
17
|
-
AWS credentials are read from environment:
|
|
18
|
-
$ AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx npx @archildata/just-bash s3://my-bucket -k adt_xxx
|
|
19
|
-
|
|
20
|
-
Traditional usage (direct connection):
|
|
21
|
-
$ npx @archildata/just-bash aws-us-east-1 myaccount/mydisk
|
|
22
|
-
$ npx @archildata/just-bash --region aws-us-east-1 --disk myaccount/mydisk
|
|
23
|
-
$ ARCHIL_DISK_TOKEN=xxx npx @archildata/just-bash aws-us-east-1 myaccount/mydisk
|
|
24
|
-
|
|
25
|
-
Subdirectory mounting (mount a subdirectory as the root):
|
|
26
|
-
$ npx @archildata/just-bash aws-us-east-1 myaccount/mydisk:/data/project
|
|
27
|
-
|
|
28
|
-
Environment variables:
|
|
29
|
-
ARCHIL_API_KEY API key for disk management
|
|
30
|
-
ARCHIL_REGION Fallback for --region
|
|
31
|
-
ARCHIL_DISK Fallback for --disk
|
|
32
|
-
ARCHIL_DISK_TOKEN Fallback for --token (recommended for secrets)
|
|
33
|
-
ARCHIL_LOG_LEVEL Fallback for --log-level
|
|
34
|
-
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY S3 credentials for bucket mode
|
|
35
|
-
`);
|
|
36
|
-
program.parse();
|
|
37
|
-
var opts = program.opts();
|
|
38
|
-
var args = program.args;
|
|
39
|
-
var isS3Bucket = args[0]?.startsWith("s3://");
|
|
40
|
-
function parseS3Url(url) {
|
|
41
|
-
const match = url.match(/^s3:\/\/([^/]+)(\/.*)?$/);
|
|
42
|
-
if (!match) {
|
|
43
|
-
throw new Error(`Invalid S3 URL: ${url}`);
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
bucket: match[1],
|
|
47
|
-
prefix: match[2]?.slice(1) || void 0
|
|
48
|
-
// Remove leading /
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function diskNameFromBucket(bucket) {
|
|
52
|
-
return `s3-${bucket.replace(/[^a-zA-Z0-9-]/g, "-")}`;
|
|
53
|
-
}
|
|
54
|
-
function findDiskForBucket(disks, bucketName) {
|
|
55
|
-
return disks.find(
|
|
56
|
-
(disk) => disk.mounts?.some(
|
|
57
|
-
(mount) => mount.type === "s3" && mount.config?.bucketName === bucketName
|
|
58
|
-
)
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
async function runS3BucketMode() {
|
|
62
|
-
const s3Url = args[0];
|
|
63
|
-
const logLevel = opts.logLevel || process.env.ARCHIL_LOG_LEVEL;
|
|
64
|
-
const region = opts.region || process.env.ARCHIL_REGION || "aws-us-east-1";
|
|
65
|
-
const bucketRegion = opts.bucketRegion || "us-east-1";
|
|
66
|
-
const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
67
|
-
const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
68
|
-
if (!awsAccessKeyId || !awsSecretAccessKey) {
|
|
69
|
-
console.error("Error: AWS credentials required for S3 bucket mode");
|
|
70
|
-
console.error("");
|
|
71
|
-
console.error("Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables:");
|
|
72
|
-
console.error(" AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx npx @archildata/just-bash s3://my-bucket -k adt_xxx");
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
const { bucket, prefix } = parseS3Url(s3Url);
|
|
76
|
-
const combinedPrefix = opts.bucketPrefix ? opts.bucketPrefix + (prefix ? "/" + prefix : "") : prefix;
|
|
77
|
-
console.log("Archil S3 Quick Start");
|
|
78
|
-
console.log("=====================");
|
|
79
|
-
console.log(` Bucket: ${bucket}`);
|
|
80
|
-
if (combinedPrefix) {
|
|
81
|
-
console.log(` Prefix: ${combinedPrefix}`);
|
|
82
|
-
}
|
|
83
|
-
console.log(` Region: ${region}`);
|
|
84
|
-
console.log(` Bucket Region: ${bucketRegion}`);
|
|
85
|
-
console.log("");
|
|
86
|
-
let archil;
|
|
87
|
-
try {
|
|
88
|
-
archil = new Archil({
|
|
89
|
-
apiKey: opts.apiKey,
|
|
90
|
-
region
|
|
91
|
-
});
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.error(err instanceof Error ? err.message : err);
|
|
94
|
-
console.error("");
|
|
95
|
-
console.error("Usage:");
|
|
96
|
-
console.error(" npx @archildata/just-bash s3://my-bucket --api-key adt_xxx");
|
|
97
|
-
console.error("");
|
|
98
|
-
console.error("Or set ARCHIL_API_KEY environment variable:");
|
|
99
|
-
console.error(" ARCHIL_API_KEY=adt_xxx npx @archildata/just-bash s3://my-bucket");
|
|
100
|
-
process.exit(1);
|
|
101
|
-
}
|
|
102
|
-
console.log("Checking for existing disk...");
|
|
103
|
-
let disk;
|
|
104
|
-
let mountToken;
|
|
105
|
-
try {
|
|
106
|
-
const disks = await archil.disks.list();
|
|
107
|
-
disk = findDiskForBucket(disks, bucket);
|
|
108
|
-
if (disk) {
|
|
109
|
-
console.log(`Found existing disk: ${disk.name} (${disk.id})`);
|
|
110
|
-
}
|
|
111
|
-
} catch (err) {
|
|
112
|
-
console.error("Failed to list disks:", err instanceof Error ? err.message : err);
|
|
113
|
-
process.exit(1);
|
|
114
|
-
}
|
|
115
|
-
if (!disk) {
|
|
116
|
-
const diskName = diskNameFromBucket(bucket);
|
|
117
|
-
console.log(`Creating new disk: ${diskName}`);
|
|
118
|
-
try {
|
|
119
|
-
const result = await archil.disks.create({
|
|
120
|
-
name: diskName,
|
|
121
|
-
mounts: [
|
|
122
|
-
{
|
|
123
|
-
type: "s3",
|
|
124
|
-
bucketName: bucket,
|
|
125
|
-
bucketPrefix: combinedPrefix,
|
|
126
|
-
accessKeyId: awsAccessKeyId,
|
|
127
|
-
secretAccessKey: awsSecretAccessKey
|
|
128
|
-
}
|
|
129
|
-
]
|
|
130
|
-
});
|
|
131
|
-
disk = result.disk;
|
|
132
|
-
mountToken = result.token ?? void 0;
|
|
133
|
-
console.log(`Created disk: ${disk.name} (${disk.id})`);
|
|
134
|
-
} catch (err) {
|
|
135
|
-
console.error("Failed to create disk:", err instanceof Error ? err.message : err);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (!mountToken) {
|
|
140
|
-
try {
|
|
141
|
-
const { token } = await disk.createToken("just-bash");
|
|
142
|
-
mountToken = token;
|
|
143
|
-
} catch (err) {
|
|
144
|
-
console.error("Failed to create mount token:", err instanceof Error ? err.message : err);
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
console.log("Connecting...");
|
|
149
|
-
let client;
|
|
150
|
-
try {
|
|
151
|
-
client = await disk.mount({ authToken: mountToken, logLevel });
|
|
152
|
-
console.log("Connected!");
|
|
153
|
-
} catch (err) {
|
|
154
|
-
console.error("Failed to connect:", err instanceof Error ? err.message : err);
|
|
155
|
-
process.exit(1);
|
|
156
|
-
}
|
|
157
|
-
return { client, diskName: disk.name, subdirectory: void 0 };
|
|
158
|
-
}
|
|
159
|
-
async function runDirectMode() {
|
|
160
|
-
const region = args[0] || opts.region || process.env.ARCHIL_REGION;
|
|
161
|
-
const rawDisk = args[1] || opts.disk || process.env.ARCHIL_DISK;
|
|
162
|
-
const authToken = opts.token || process.env.ARCHIL_DISK_TOKEN;
|
|
163
|
-
const logLevel = opts.logLevel || process.env.ARCHIL_LOG_LEVEL;
|
|
164
|
-
let diskName;
|
|
165
|
-
let subdirectory;
|
|
166
|
-
if (rawDisk) {
|
|
167
|
-
const colonIdx = rawDisk.indexOf(":/");
|
|
168
|
-
if (colonIdx !== -1) {
|
|
169
|
-
diskName = rawDisk.substring(0, colonIdx);
|
|
170
|
-
const subdir = rawDisk.substring(colonIdx + 1).replace(/^\/+|\/+$/g, "");
|
|
171
|
-
if (subdir) {
|
|
172
|
-
subdirectory = subdir;
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
diskName = rawDisk;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (!region || !diskName) {
|
|
179
|
-
console.error("Error: region and disk are required\n");
|
|
180
|
-
console.error("Usage:");
|
|
181
|
-
console.error(" npx @archildata/just-bash <region> <disk>");
|
|
182
|
-
console.error(" npx @archildata/just-bash --region <region> --disk <disk>");
|
|
183
|
-
console.error("\nQuick start with S3 bucket:");
|
|
184
|
-
console.error(" npx @archildata/just-bash s3://my-bucket --api-key adt_xxx");
|
|
185
|
-
console.error("\nExamples:");
|
|
186
|
-
console.error(" npx @archildata/just-bash aws-us-east-1 myaccount/mydisk");
|
|
187
|
-
console.error(" ARCHIL_DISK_TOKEN=xxx npx @archildata/just-bash aws-us-east-1 myaccount/mydisk");
|
|
188
|
-
console.error("\nRun with --help for more options.");
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
console.log("Connecting to Archil...");
|
|
192
|
-
console.log(` Region: ${region}`);
|
|
193
|
-
console.log(` Disk: ${diskName}`);
|
|
194
|
-
if (subdirectory) {
|
|
195
|
-
console.log(` Subdirectory: ${subdirectory}`);
|
|
196
|
-
}
|
|
197
|
-
console.log(` Auth: ${authToken ? "token" : "IAM"}`);
|
|
198
|
-
if (logLevel) {
|
|
199
|
-
console.log(` Log level: ${logLevel}`);
|
|
200
|
-
}
|
|
201
|
-
console.log("");
|
|
202
|
-
let client;
|
|
203
|
-
try {
|
|
204
|
-
client = await ArchilClient.connect({
|
|
205
|
-
region,
|
|
206
|
-
diskName,
|
|
207
|
-
authToken: authToken || void 0,
|
|
208
|
-
logLevel
|
|
209
|
-
});
|
|
210
|
-
console.log("Connected!");
|
|
211
|
-
} catch (err) {
|
|
212
|
-
console.error("Failed to connect:", err instanceof Error ? err.message : err);
|
|
213
|
-
process.exit(1);
|
|
214
|
-
}
|
|
215
|
-
return { client, diskName, subdirectory };
|
|
216
|
-
}
|
|
217
|
-
async function main() {
|
|
218
|
-
const { client, diskName, subdirectory } = isS3Bucket ? await runS3BucketMode() : await runDirectMode();
|
|
219
|
-
const fs = await ArchilFs.create(client, { subdirectory });
|
|
220
|
-
const bash = new Bash({ fs, customCommands: [createArchilCommand(client, fs)] });
|
|
221
|
-
let cleaningUp = false;
|
|
222
|
-
const cleanup = async (signal) => {
|
|
223
|
-
if (cleaningUp) return;
|
|
224
|
-
cleaningUp = true;
|
|
225
|
-
if (signal) {
|
|
226
|
-
console.log(`
|
|
227
|
-
Received ${signal}, cleaning up...`);
|
|
228
|
-
} else {
|
|
229
|
-
console.log("\nGoodbye!");
|
|
230
|
-
}
|
|
231
|
-
try {
|
|
232
|
-
const released = await client.close();
|
|
233
|
-
if (released > 0) {
|
|
234
|
-
console.log(`Released ${released} delegation${released > 1 ? "s" : ""}`);
|
|
235
|
-
}
|
|
236
|
-
} catch (err) {
|
|
237
|
-
console.error("Error during cleanup:", err instanceof Error ? err.message : err);
|
|
238
|
-
}
|
|
239
|
-
process.exit(0);
|
|
240
|
-
};
|
|
241
|
-
process.on("SIGINT", () => cleanup("SIGINT"));
|
|
242
|
-
process.on("SIGTERM", () => cleanup("SIGTERM"));
|
|
243
|
-
process.on("SIGHUP", () => cleanup("SIGHUP"));
|
|
244
|
-
console.log("");
|
|
245
|
-
console.log("=== Archil just-bash shell ===");
|
|
246
|
-
console.log(`Connected to: ${diskName}${subdirectory ? ":" + subdirectory : ""}`);
|
|
247
|
-
console.log("");
|
|
248
|
-
console.log("Type bash commands to interact with the filesystem.");
|
|
249
|
-
console.log("Special commands:");
|
|
250
|
-
console.log(" archil checkout [--force] <path> - Acquire write delegation");
|
|
251
|
-
console.log(" archil checkin <path> - Release write delegation");
|
|
252
|
-
console.log(" archil list-delegations - Show held delegations");
|
|
253
|
-
console.log(" archil help - Show archil commands");
|
|
254
|
-
console.log("Type 'exit' or Ctrl+D to quit.");
|
|
255
|
-
console.log("");
|
|
256
|
-
const rl = readline.createInterface({
|
|
257
|
-
input: process.stdin,
|
|
258
|
-
output: process.stdout,
|
|
259
|
-
prompt: "archil$ "
|
|
260
|
-
});
|
|
261
|
-
let cwd = "/";
|
|
262
|
-
const prompt = () => {
|
|
263
|
-
rl.setPrompt(`archil:${cwd}$ `);
|
|
264
|
-
rl.prompt();
|
|
265
|
-
};
|
|
266
|
-
prompt();
|
|
267
|
-
rl.on("line", async (line) => {
|
|
268
|
-
const trimmed = line.trim();
|
|
269
|
-
if (trimmed === "exit" || trimmed === "quit") {
|
|
270
|
-
await cleanup();
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
if (!trimmed) {
|
|
274
|
-
prompt();
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
rl.pause();
|
|
278
|
-
try {
|
|
279
|
-
const result = await bash.exec(trimmed, {
|
|
280
|
-
cwd,
|
|
281
|
-
env: {
|
|
282
|
-
HOME: "/",
|
|
283
|
-
USER: "archil",
|
|
284
|
-
PWD: cwd
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
if (result.stdout) {
|
|
288
|
-
process.stdout.write(result.stdout);
|
|
289
|
-
if (!result.stdout.endsWith("\n")) {
|
|
290
|
-
console.log("");
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if (result.stderr) {
|
|
294
|
-
process.stderr.write(result.stderr);
|
|
295
|
-
if (!result.stderr.endsWith("\n")) {
|
|
296
|
-
console.error("");
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (result.env?.PWD && result.env.PWD !== cwd) {
|
|
300
|
-
cwd = result.env.PWD;
|
|
301
|
-
}
|
|
302
|
-
} catch (err) {
|
|
303
|
-
console.error("Error:", err instanceof Error ? err.message : err);
|
|
304
|
-
}
|
|
305
|
-
rl.resume();
|
|
306
|
-
prompt();
|
|
307
|
-
});
|
|
308
|
-
rl.on("close", () => cleanup());
|
|
309
|
-
}
|
|
310
|
-
main().catch((err) => {
|
|
311
|
-
console.error("Fatal error:", err);
|
|
312
|
-
process.exit(1);
|
|
313
|
-
});
|